feat: new alternate syntax and switch to black + isort (yeah, maybe not the best time, but that is done).

This commit is contained in:
Romain Dorgueil
2018-07-29 18:21:56 +01:00
parent 3094e43f9f
commit 89dda0dca6
123 changed files with 1672 additions and 1640 deletions

View File

@ -16,49 +16,49 @@ from bonobo.util.bags import BagType
### Named Tuples
################################################################################
TBag = BagType('TBag', ('x', 'y', 'z')) # type used for pickle tests
TBag = BagType("TBag", ("x", "y", "z")) # type used for pickle tests
class TestBagType(unittest.TestCase):
def _create(self, *fields, typename='abc'):
def _create(self, *fields, typename="abc"):
bt = BagType(typename, fields)
assert bt._fields == fields
assert len(bt._fields) == len(bt._attrs)
return bt
def test_factory(self):
Point = BagType('Point', ('x', 'y'))
self.assertEqual(Point.__name__, 'Point')
Point = BagType("Point", ("x", "y"))
self.assertEqual(Point.__name__, "Point")
self.assertEqual(Point.__slots__, ())
self.assertEqual(Point.__module__, __name__)
self.assertEqual(Point.__getitem__, tuple.__getitem__)
assert Point._fields == ('x', 'y')
assert Point._attrs == ('x', 'y')
assert Point._fields == ("x", "y")
assert Point._attrs == ("x", "y")
self.assertRaises(ValueError, BagType, 'abc%', ('efg', 'ghi')) # type has non-alpha char
self.assertRaises(ValueError, BagType, 'class', ('efg', 'ghi')) # type has keyword
self.assertRaises(ValueError, BagType, '9abc', ('efg', 'ghi')) # type starts with digit
self.assertRaises(ValueError, BagType, "abc%", ("efg", "ghi")) # type has non-alpha char
self.assertRaises(ValueError, BagType, "class", ("efg", "ghi")) # type has keyword
self.assertRaises(ValueError, BagType, "9abc", ("efg", "ghi")) # type starts with digit
assert self._create('efg', 'g%hi')._attrs == ('efg', 'g_hi')
assert self._create('abc', 'class')._attrs == ('abc', '_class')
assert self._create('8efg', '9ghi')._attrs == ('_8efg', '_9ghi')
assert self._create('_efg', 'ghi')._attrs == ('_efg', 'ghi')
assert self._create("efg", "g%hi")._attrs == ("efg", "g_hi")
assert self._create("abc", "class")._attrs == ("abc", "_class")
assert self._create("8efg", "9ghi")._attrs == ("_8efg", "_9ghi")
assert self._create("_efg", "ghi")._attrs == ("_efg", "ghi")
self.assertRaises(ValueError, BagType, 'abc', ('efg', 'efg', 'ghi')) # duplicate field
self.assertRaises(ValueError, BagType, "abc", ("efg", "efg", "ghi")) # duplicate field
self._create('x1', 'y2', typename='Point0') # Verify that numbers are allowed in names
self._create('a', 'b', 'c', typename='_') # Test leading underscores in a typename
self._create("x1", "y2", typename="Point0") # Verify that numbers are allowed in names
self._create("a", "b", "c", typename="_") # Test leading underscores in a typename
bt = self._create('a!', 'a?')
assert bt._attrs == ('a0', 'a1')
x = bt('foo', 'bar')
assert x.get('a!') == 'foo'
assert x.a0 == 'foo'
assert x.get('a?') == 'bar'
assert x.a1 == 'bar'
bt = self._create("a!", "a?")
assert bt._attrs == ("a0", "a1")
x = bt("foo", "bar")
assert x.get("a!") == "foo"
assert x.a0 == "foo"
assert x.get("a?") == "bar"
assert x.a1 == "bar"
# check unicode output
bt = self._create('the', 'quick', 'brown', 'fox')
bt = self._create("the", "quick", "brown", "fox")
assert "u'" not in repr(bt._fields)
self.assertRaises(TypeError, Point._make, [11]) # catch too few args
@ -66,33 +66,33 @@ class TestBagType(unittest.TestCase):
@unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above")
def test_factory_doc_attr(self):
Point = BagType('Point', ('x', 'y'))
self.assertEqual(Point.__doc__, 'Point(x, y)')
Point = BagType("Point", ("x", "y"))
self.assertEqual(Point.__doc__, "Point(x, y)")
@unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above")
def test_doc_writable(self):
Point = BagType('Point', ('x', 'y'))
Point = BagType("Point", ("x", "y"))
self.assertEqual(Point.x.__doc__, "Alias for 'x'")
Point.x.__doc__ = 'docstring for Point.x'
self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Point.x.__doc__ = "docstring for Point.x"
self.assertEqual(Point.x.__doc__, "docstring for Point.x")
def test_name_fixer(self):
for spec, renamed in [
[('efg', 'g%hi'), ('efg', 'g_hi')], # field with non-alpha char
[('abc', 'class'), ('abc', '_class')], # field has keyword
[('8efg', '9ghi'), ('_8efg', '_9ghi')], # field starts with digit
[('abc', '_efg'), ('abc', '_efg')], # field with leading underscore
[('abc', '', 'x'), ('abc', '_0', 'x')], # fieldname is a space
[('&', '¨', '*'), ('_0', '_1', '_2')], # Duplicate attrs, in theory
[("efg", "g%hi"), ("efg", "g_hi")], # field with non-alpha char
[("abc", "class"), ("abc", "_class")], # field has keyword
[("8efg", "9ghi"), ("_8efg", "_9ghi")], # field starts with digit
[("abc", "_efg"), ("abc", "_efg")], # field with leading underscore
[("abc", "", "x"), ("abc", "_0", "x")], # fieldname is a space
[("&", "¨", "*"), ("_0", "_1", "_2")], # Duplicate attrs, in theory
]:
assert self._create(*spec)._attrs == renamed
def test_module_parameter(self):
NT = BagType('NT', ['x', 'y'], module=collections)
NT = BagType("NT", ["x", "y"], module=collections)
self.assertEqual(NT.__module__, collections)
def test_instance(self):
Point = self._create('x', 'y', typename='Point')
Point = self._create("x", "y", typename="Point")
p = Point(11, 22)
self.assertEqual(p, Point(x=11, y=22))
self.assertEqual(p, Point(11, y=22))
@ -101,12 +101,12 @@ class TestBagType(unittest.TestCase):
self.assertEqual(p, Point(**dict(x=11, y=22)))
self.assertRaises(TypeError, Point, 1) # too few args
self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
self.assertEqual(repr(p), 'Point(x=11, y=22)')
self.assertNotIn('__weakref__', dir(p))
self.assertRaises(TypeError, eval, "Point(XXX=1, y=2)", locals()) # wrong keyword argument
self.assertRaises(TypeError, eval, "Point(x=1)", locals()) # missing keyword argument
self.assertEqual(repr(p), "Point(x=11, y=22)")
self.assertNotIn("__weakref__", dir(p))
self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
self.assertEqual(p._fields, ("x", "y")) # test _fields attribute
self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
@ -115,13 +115,13 @@ class TestBagType(unittest.TestCase):
except ValueError:
pass
else:
self._fail('Did not detect an incorrect fieldname')
self._fail("Did not detect an incorrect fieldname")
p = Point(x=11, y=22)
self.assertEqual(repr(p), 'Point(x=11, y=22)')
self.assertEqual(repr(p), "Point(x=11, y=22)")
def test_tupleness(self):
Point = BagType('Point', ('x', 'y'))
Point = BagType("Point", ("x", "y"))
p = Point(11, 22)
self.assertIsInstance(p, tuple)
@ -137,29 +137,29 @@ class TestBagType(unittest.TestCase):
self.assertEqual(p.x, x)
self.assertEqual(p.y, y)
self.assertRaises(AttributeError, eval, 'p.z', locals())
self.assertRaises(AttributeError, eval, "p.z", locals())
def test_odd_sizes(self):
Zero = BagType('Zero', ())
Zero = BagType("Zero", ())
self.assertEqual(Zero(), ())
self.assertEqual(Zero._make([]), ())
self.assertEqual(repr(Zero()), 'Zero()')
self.assertEqual(repr(Zero()), "Zero()")
self.assertEqual(Zero()._asdict(), {})
self.assertEqual(Zero()._fields, ())
Dot = BagType('Dot', ('d', ))
self.assertEqual(Dot(1), (1, ))
self.assertEqual(Dot._make([1]), (1, ))
Dot = BagType("Dot", ("d",))
self.assertEqual(Dot(1), (1,))
self.assertEqual(Dot._make([1]), (1,))
self.assertEqual(Dot(1).d, 1)
self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
self.assertEqual(Dot(1)._asdict(), {'d': 1})
self.assertEqual(Dot(1)._replace(d=999), (999, ))
self.assertEqual(Dot(1)._fields, ('d', ))
self.assertEqual(repr(Dot(1)), "Dot(d=1)")
self.assertEqual(Dot(1)._asdict(), {"d": 1})
self.assertEqual(Dot(1)._replace(d=999), (999,))
self.assertEqual(Dot(1)._fields, ("d",))
n = 5000 if sys.version_info >= (3, 7) else 254
names = list(set(''.join([choice(string.ascii_letters) for j in range(10)]) for i in range(n)))
names = list(set("".join([choice(string.ascii_letters) for j in range(10)]) for i in range(n)))
n = len(names)
Big = BagType('Big', names)
Big = BagType("Big", names)
b = Big(*range(n))
self.assertEqual(b, tuple(range(n)))
self.assertEqual(Big._make(range(n)), tuple(range(n)))
@ -178,14 +178,14 @@ class TestBagType(unittest.TestCase):
def test_pickle(self):
p = TBag(x=10, y=20, z=30)
for module in (pickle, ):
loads = getattr(module, 'loads')
dumps = getattr(module, 'dumps')
for module in (pickle,):
loads = getattr(module, "loads")
dumps = getattr(module, "dumps")
for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
q = loads(dumps(p, protocol))
self.assertEqual(p, q)
self.assertEqual(p._fields, q._fields)
self.assertNotIn(b'OrderedDict', dumps(p, protocol))
self.assertNotIn(b"OrderedDict", dumps(p, protocol))
def test_copy(self):
p = TBag(x=10, y=20, z=30)
@ -197,7 +197,7 @@ class TestBagType(unittest.TestCase):
def test_name_conflicts(self):
# Some names like "self", "cls", "tuple", "itemgetter", and "property"
# failed when used as field names. Test to make sure these now work.
T = BagType('T', ('itemgetter', 'property', 'self', 'cls', 'tuple'))
T = BagType("T", ("itemgetter", "property", "self", "cls", "tuple"))
t = T(1, 2, 3, 4, 5)
self.assertEqual(t, (1, 2, 3, 4, 5))
newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
@ -206,28 +206,194 @@ class TestBagType(unittest.TestCase):
# Broader test of all interesting names taken from the code, old
# template, and an example
words = {
'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create', 'Encountered', 'Expected', 'Field', 'For',
'Got', 'Helper', 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note', 'OrderedDict', 'Point',
'Return', 'Returns', 'Type', 'TypeError', 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible',
'add', 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments', 'automatically', 'be', 'build',
'builtins', 'but', 'by', 'cannot', 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict', 'dictionary', 'doc', 'docstring',
'docstrings', 'duplicate', 'effect', 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame', 'function', 'functions', 'generate',
'getter', 'got', 'greater', 'has', 'help', 'identifiers', 'indexable', 'instance', 'instantiate',
'interning', 'introspection', 'isidentifier', 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword',
'keywords', 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata', 'method', 'methods',
'module', 'module_name', 'must', 'name', 'named', 'namedtuple', 'namedtuple_', 'names', 'namespace',
'needs', 'new', 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option', 'p', 'particular',
'pickle', 'pickling', 'plain', 'pop', 'positional', 'property', 'r', 'regular', 'rename', 'replace',
'replacing', 'repr', 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen', 'sequence',
'set', 'side', 'specified', 'split', 'start', 'startswith', 'step', 'str', 'string', 'strings', 'subclass',
'sys', 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple_new', 'type', 'typename', 'underscore',
'unexpected', 'unpack', 'up', 'use', 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
'which', 'work', 'x', 'y', 'z', 'zip'
"Alias",
"At",
"AttributeError",
"Build",
"Bypass",
"Create",
"Encountered",
"Expected",
"Field",
"For",
"Got",
"Helper",
"IronPython",
"Jython",
"KeyError",
"Make",
"Modify",
"Note",
"OrderedDict",
"Point",
"Return",
"Returns",
"Type",
"TypeError",
"Used",
"Validate",
"ValueError",
"Variables",
"a",
"accessible",
"add",
"added",
"all",
"also",
"an",
"arg_list",
"args",
"arguments",
"automatically",
"be",
"build",
"builtins",
"but",
"by",
"cannot",
"class_namespace",
"classmethod",
"cls",
"collections",
"convert",
"copy",
"created",
"creation",
"d",
"debugging",
"defined",
"dict",
"dictionary",
"doc",
"docstring",
"docstrings",
"duplicate",
"effect",
"either",
"enumerate",
"environments",
"error",
"example",
"exec",
"f",
"f_globals",
"field",
"field_names",
"fields",
"formatted",
"frame",
"function",
"functions",
"generate",
"getter",
"got",
"greater",
"has",
"help",
"identifiers",
"indexable",
"instance",
"instantiate",
"interning",
"introspection",
"isidentifier",
"isinstance",
"itemgetter",
"iterable",
"join",
"keyword",
"keywords",
"kwds",
"len",
"like",
"list",
"map",
"maps",
"message",
"metadata",
"method",
"methods",
"module",
"module_name",
"must",
"name",
"named",
"namedtuple",
"namedtuple_",
"names",
"namespace",
"needs",
"new",
"nicely",
"num_fields",
"number",
"object",
"of",
"operator",
"option",
"p",
"particular",
"pickle",
"pickling",
"plain",
"pop",
"positional",
"property",
"r",
"regular",
"rename",
"replace",
"replacing",
"repr",
"repr_fmt",
"representation",
"result",
"reuse_itemgetter",
"s",
"seen",
"sequence",
"set",
"side",
"specified",
"split",
"start",
"startswith",
"step",
"str",
"string",
"strings",
"subclass",
"sys",
"targets",
"than",
"the",
"their",
"this",
"to",
"tuple_new",
"type",
"typename",
"underscore",
"unexpected",
"unpack",
"up",
"use",
"used",
"user",
"valid",
"values",
"variable",
"verbose",
"where",
"which",
"work",
"x",
"y",
"z",
"zip",
}
sorted_words = tuple(sorted(words))
T = BagType('T', sorted_words)
T = BagType("T", sorted_words)
# test __new__
values = tuple(range(len(words)))
t = T(*values)
@ -252,27 +418,39 @@ class TestBagType(unittest.TestCase):
self.assertEqual(t.__getnewargs__(), values)
def test_repr(self):
A = BagType('A', ('x', ))
self.assertEqual(repr(A(1)), 'A(x=1)')
A = BagType("A", ("x",))
self.assertEqual(repr(A(1)), "A(x=1)")
# repr should show the name of the subclass
class B(A):
pass
self.assertEqual(repr(B(1)), 'B(x=1)')
self.assertEqual(repr(B(1)), "B(x=1)")
def test_namedtuple_subclass_issue_24931(self):
class Point(BagType('_Point', ['x', 'y'])):
class Point(BagType("_Point", ["x", "y"])):
pass
a = Point(3, 4)
self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
self.assertEqual(a._asdict(), OrderedDict([("x", 3), ("y", 4)]))
a.w = 5
self.assertEqual(a.__dict__, {'w': 5})
self.assertEqual(a.__dict__, {"w": 5})
def test_annoying_attribute_names(self):
self._create(
'__slots__', '__getattr__', '_attrs', '_fields', '__new__', '__getnewargs__', '__repr__', '_make', 'get',
'_replace', '_asdict', '_cls', 'self', 'tuple'
"__slots__",
"__getattr__",
"_attrs",
"_fields",
"__new__",
"__getnewargs__",
"__repr__",
"_make",
"get",
"_replace",
"_asdict",
"_cls",
"self",
"tuple",
)