diff options
author | Raphaël Barrois <raphael.barrois@polytechnique.org> | 2012-02-24 01:14:30 +0100 |
---|---|---|
committer | Raphaël Barrois <raphael.barrois@polytechnique.org> | 2012-02-24 01:14:30 +0100 |
commit | dc16881ebf674295a3e855bfc4798a0ce8bd94d2 (patch) | |
tree | 2e379c8814c41784945968f0229b117217aad10a /factory | |
parent | 3663c1090f6ce016ebc0e9266c4cd4e85796984b (diff) | |
download | factory-boy-dc16881ebf674295a3e855bfc4798a0ce8bd94d2.tar factory-boy-dc16881ebf674295a3e855bfc4798a0ce8bd94d2.tar.gz |
Improve the 'SelfAttribute' syntax.v1.1.0
Signed-off-by: Raphaël Barrois <raphael.barrois@polytechnique.org>
Diffstat (limited to 'factory')
-rw-r--r-- | factory/containers.py | 2 | ||||
-rw-r--r-- | factory/declarations.py | 42 |
2 files changed, 26 insertions, 18 deletions
diff --git a/factory/containers.py b/factory/containers.py index fda9073..2f92f62 100644 --- a/factory/containers.py +++ b/factory/containers.py @@ -26,7 +26,7 @@ from factory import declarations #: String for splitting an attribute name into a #: (subfactory_name, subfactory_field) tuple. -ATTR_SPLITTER = declarations.ATTR_SPLITTER +ATTR_SPLITTER = '__' class CyclicDefinitionError(Exception): diff --git a/factory/declarations.py b/factory/declarations.py index 08598e5..5fe427c 100644 --- a/factory/declarations.py +++ b/factory/declarations.py @@ -21,11 +21,6 @@ # THE SOFTWARE. -#: String for splitting an attribute name into a -#: (subfactory_name, subfactory_field) tuple. -ATTR_SPLITTER = '__' - - class OrderedDeclaration(object): """A factory declaration. @@ -64,27 +59,37 @@ class LazyAttribute(OrderedDeclaration): return self.function(obj) -def dig(obj, name): - """Try to retrieve the given attribute of an object, using ATTR_SPLITTER. +class _UNSPECIFIED(object): + pass + - If ATTR_SPLITTER is '__', dig(foo, 'a__b__c') is equivalent to foo.a.b.c. +def deepgetattr(obj, name, default=_UNSPECIFIED): + """Try to retrieve the given attribute of an object, digging on '.'. + + This is an extended getattr, digging deeper if '.' is found. Args: obj (object): the object of which an attribute should be read name (str): the name of an attribute to look up. + default (object): the default value to use if the attribute wasn't found Returns: - the attribute pointed to by 'name', according to ATTR_SPLITTER. + the attribute pointed to by 'name', splitting on '.'. Raises: AttributeError: if obj has no 'name' attribute. """ - may_split = (ATTR_SPLITTER in name and not name.startswith(ATTR_SPLITTER)) - if may_split and not hasattr(obj, name): - attr, subname = name.split(ATTR_SPLITTER, 1) - return dig(getattr(obj, attr), subname) - else: - return getattr(obj, name) + try: + if '.' in name: + attr, subname = name.split('.', 1) + return deepgetattr(getattr(obj, attr), subname, default) + else: + return getattr(obj, name) + except AttributeError: + if default is _UNSPECIFIED: + raise + else: + return default class SelfAttribute(OrderedDeclaration): @@ -92,14 +97,17 @@ class SelfAttribute(OrderedDeclaration): Attributes: attribute_name (str): the name of the attribute to copy. + default (object): the default value to use if the attribute doesn't + exist. """ - def __init__(self, attribute_name, *args, **kwargs): + def __init__(self, attribute_name, default=_UNSPECIFIED, *args, **kwargs): super(SelfAttribute, self).__init__(*args, **kwargs) self.attribute_name = attribute_name + self.default = default def evaluate(self, sequence, obj, containers=()): - return dig(obj, self.attribute_name) + return deepgetattr(obj, self.attribute_name, self.default) class Sequence(OrderedDeclaration): |