Skip to content

Commit d7a11f5

Browse files
committed
Supporting Python 2.6
1 parent 7a253fa commit d7a11f5

File tree

20 files changed

+379
-28
lines changed

20 files changed

+379
-28
lines changed

LICENSE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ Python Toolbox includes third-party Python packages as subpackages that are used
2525
* `linecache2` by "Testing-cabal" and others, PSF license.
2626
* `traceback2` by "Testing-cabal" and others, PSF license.
2727
* `six` by Benjamin Peterson and others, MIT license.
28+
* `ordereddict` by Raymond Hettinger and others, MIT license.
29+
* `functools` by Python-dev and others, PSF license.
2830

README.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ Python Toolbox includes third-party Python packages as subpackages that are used
8484
* `linecache2` by "Testing-cabal" and others, PSF license.
8585
* `traceback2` by "Testing-cabal" and others, PSF license.
8686
* `six` by Benjamin Peterson and others, MIT license.
87+
* `ordereddict` by Raymond Hettinger and others, MIT license.
88+
* `functools` by Python-dev and others, PSF license.
8789

8890

8991
------------------------------------------------------------------

setup.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
# #
1414
if sys.version_info[:2] <= (2, 6):
1515
raise Exception(
16-
"You're using Python <= 2.6, but this package requires either Python "
17-
"2.7, or 3.3 or above, so you can't use it unless you upgrade your "
18-
"Python version."
16+
"You're using Python <= 2.5, but this package requires either Python "
17+
"2.6/2.7, or 3.3 or above, so you can't use it unless you upgrade "
18+
"your Python version."
1919
)
2020
if sys.version_info[0] == 3 and sys.version_info[1] <= 2:
2121
raise Exception(
2222
"You're using Python <= 3.2, but this package requires either Python "
23-
"3.3 or above, or Python 2.7, so you can't use it unless you upgrade "
24-
"your Python version."
23+
"3.3 or above, or Python 2.6/2.7, so you can't use it unless you "
24+
"upgrade your Python version."
2525
)
2626
# #
2727
### Finished confirming correct Python version. ###############################
@@ -149,6 +149,7 @@ def get_packages():
149149
'License :: OSI Approved :: MIT License',
150150
'Operating System :: OS Independent',
151151
'Programming Language :: Python',
152+
'Programming Language :: Python :: 2.6',
152153
'Programming Language :: Python :: 2.7',
153154
'Programming Language :: Python :: 3.3',
154155
'Programming Language :: Python :: 3.4',

source_py2/python_toolbox/MIT_license.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ Python Toolbox includes third-party Python packages as subpackages that are used
2525
* `linecache2` by "Testing-cabal" and others, PSF license.
2626
* `traceback2` by "Testing-cabal" and others, PSF license.
2727
* `six` by Benjamin Peterson and others, MIT license.
28-
28+
* `ordereddict` by Raymond Hettinger and others, MIT license.
29+
* `functools` by Python-dev and others, PSF license.

source_py2/python_toolbox/_bootstrap/bootstrap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
raise Exception("This is a Python 2.x distribution of `python_toolbox`, "
1010
"and you're using Python 3.x. Please get the Python 3.x "
1111
"distribution.")
12-
if sys.version_info[1] <= 6:
12+
if sys.version_info[1] <= 5:
1313
raise Exception(
14-
"You're using Python <= 2.6, but this package requires Python 2.7, "
14+
"You're using Python <= 2.5, but this package requires Python 2.6, "
1515
"(or Python 3.3+ on a different distribution,) so you can't use it "
1616
"unless you upgrade your Python version."
1717
)

source_py2/python_toolbox/cute_inspect/__init__.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,101 @@
77
import inspect
88

99
getargspec = inspect.getargspec
10-
getcallargs = inspect.getcallargs
1110
getsource = inspect.getsource
11+
try:
12+
getcallargs = inspect.getcallargs
13+
except AttributeError:
14+
# No `getcallargs` on Python 2.6
15+
def getcallargs(func, *positional, **named):
16+
"""Get the mapping of arguments to values.
17+
18+
A dict is returned, with keys the function argument names (including the
19+
names of the * and ** arguments, if any), and values the respective bound
20+
values from 'positional' and 'named'."""
21+
# from inspect import *
22+
args, varargs, varkw, defaults = getargspec(func)
23+
f_name = func.__name__
24+
arg2value = {}
25+
26+
# The following closures are basically because of tuple parameter unpacking.
27+
assigned_tuple_params = []
28+
def assign(arg, value):
29+
if isinstance(arg, str):
30+
arg2value[arg] = value
31+
else:
32+
assigned_tuple_params.append(arg)
33+
value = iter(value)
34+
for i, subarg in enumerate(arg):
35+
try:
36+
subvalue = next(value)
37+
except StopIteration:
38+
raise ValueError('need more than %d %s to unpack' %
39+
(i, 'values' if i > 1 else 'value'))
40+
assign(subarg,subvalue)
41+
try:
42+
next(value)
43+
except StopIteration:
44+
pass
45+
else:
46+
raise ValueError('too many values to unpack')
47+
def is_assigned(arg):
48+
if isinstance(arg,str):
49+
return arg in arg2value
50+
return arg in assigned_tuple_params
51+
if ismethod(func) and func.im_self is not None:
52+
# implicit 'self' (or 'cls' for classmethods) argument
53+
positional = (func.im_self,) + positional
54+
num_pos = len(positional)
55+
num_total = num_pos + len(named)
56+
num_args = len(args)
57+
num_defaults = len(defaults) if defaults else 0
58+
for arg, value in zip(args, positional):
59+
assign(arg, value)
60+
if varargs:
61+
if num_pos > num_args:
62+
assign(varargs, positional[-(num_pos-num_args):])
63+
else:
64+
assign(varargs, ())
65+
elif 0 < num_args < num_pos:
66+
raise TypeError('%s() takes %s %d %s (%d given)' % (
67+
f_name, 'at most' if defaults else 'exactly', num_args,
68+
'arguments' if num_args > 1 else 'argument', num_total))
69+
elif num_args == 0 and num_total:
70+
if varkw:
71+
if num_pos:
72+
# XXX: We should use num_pos, but Python also uses num_total:
73+
raise TypeError('%s() takes exactly 0 arguments '
74+
'(%d given)' % (f_name, num_total))
75+
else:
76+
raise TypeError('%s() takes no arguments (%d given)' %
77+
(f_name, num_total))
78+
for arg in args:
79+
if isinstance(arg, str) and arg in named:
80+
if is_assigned(arg):
81+
raise TypeError("%s() got multiple values for keyword "
82+
"argument '%s'" % (f_name, arg))
83+
else:
84+
assign(arg, named.pop(arg))
85+
if defaults: # fill in any missing values with the defaults
86+
for arg, value in zip(args[-num_defaults:], defaults):
87+
if not is_assigned(arg):
88+
assign(arg, value)
89+
if varkw:
90+
assign(varkw, named)
91+
elif named:
92+
unexpected = next(iter(named))
93+
if isinstance(unexpected, unicode):
94+
unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace')
95+
raise TypeError("%s() got an unexpected keyword argument '%s'" %
96+
(f_name, unexpected))
97+
unassigned = num_args - len([arg for arg in args if is_assigned(arg)])
98+
if unassigned:
99+
num_required = num_args - num_defaults
100+
raise TypeError('%s() takes %s %d %s (%d given)' % (
101+
f_name, 'at least' if defaults else 'exactly', num_required,
102+
'arguments' if num_required > 1 else 'argument', num_total))
103+
return arg2value
104+
12105

13106
###############################################################################
14107

source_py2/python_toolbox/misc_tools/misc_tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def getted_vars(thing, _getattr=getattr):
9191
# todo: can make "fallback" option, to use value from original `vars` if
9292
# get is unsuccessful.
9393
my_vars = vars(thing)
94-
return {name: _getattr(thing, name) for name in my_vars.iterkeys()}
94+
return dict((name, _getattr(thing, name)) for name in my_vars.iterkeys())
9595

9696

9797

source_py2/python_toolbox/misc_tools/name_mangling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def mangle_attribute_name_if_needed(attribute_name, class_name):
1414
if ((not attribute_name.startswith('__')) or
1515
(len(attribute_name) + 2 >= MANGLE_LEN) or
1616
(attribute_name.endswith('__')) or
17-
set(class_name) == {'_'}):
17+
set(class_name) == set(('_',))):
1818

1919
return attribute_name
2020

source_py2/python_toolbox/nifty_collections/abstract.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import collections
66
import Queue as queue
77
import multiprocessing.queues
8+
import python_toolbox.third_party.ordereddict
89

910

1011
###############################################################################
@@ -23,7 +24,12 @@ class Ordered():
2324

2425
Ordered.register(bytearray)
2526
Ordered.register(collections.Sequence)
26-
Ordered.register(collections.OrderedDict)
27+
try:
28+
Ordered.register(collections.OrderedDict)
29+
except AttributeError:
30+
# Python 2.6
31+
pass
32+
Ordered.register(python_toolbox.third_party.ordereddict.OrderedDict)
2733
Ordered.register(collections.deque)
2834
Ordered.register(queue.Queue)
2935
Ordered.register(multiprocessing.queues.Queue)
@@ -43,8 +49,12 @@ class DefinitelyUnordered():
4349

4450
@classmethod
4551
def __subclasshook__(cls, type_):
46-
if cls is DefinitelyUnordered and \
47-
issubclass(type_, collections.OrderedDict):
52+
try:
53+
OrderedDict = collections.OrderedDict
54+
except AttributeError:
55+
# Python 2.6
56+
OrderedDict = python_toolbox.third_party.ordereddict.OrderedDict
57+
if cls is DefinitelyUnordered and issubclass(type_, OrderedDict):
4858
return False
4959
else:
5060
return NotImplemented
@@ -54,4 +64,9 @@ def __subclasshook__(cls, type_):
5464
DefinitelyUnordered.register(frozenset)
5565
DefinitelyUnordered.register(dict)
5666
DefinitelyUnordered.register(collections.defaultdict)
57-
DefinitelyUnordered.register(collections.Counter)
67+
try:
68+
DefinitelyUnordered.register(collections.Counter)
69+
except AttributeError:
70+
# Python 2.6
71+
pass
72+

source_py2/python_toolbox/nifty_collections/cute_enum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# This program is distributed under the MIT license.
33

44
from python_toolbox.third_party import enum
5-
import functools
5+
from python_toolbox.third_party import functools
66

77
from python_toolbox import caching
88

0 commit comments

Comments
 (0)