Skip to content

Commit

Permalink
[refactor] Convert Trait into Maybe declaration
Browse files Browse the repository at this point in the history
Also, convert a scalar parameter into a SimpleParameter.

FIXME: Document the 'Maybe' parameter.
  • Loading branch information
rbarrois committed Apr 7, 2017
1 parent e447662 commit c079d87
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 11 deletions.
1 change: 1 addition & 0 deletions factory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
SubFactory,
Dict,
List,
Maybe,
PostGeneration,
PostGenerationMethodCall,
RelatedFactory,
Expand Down
9 changes: 5 additions & 4 deletions factory/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,10 @@ def contribute_to_class(self, factory, meta=None, base_meta=None, base_factory=N
if params is not None:
for k, v in vars(params).items():
if not k.startswith('_'):
self.parameters[k] = v
self.parameters[k] = declarations.SimpleParameter.wrap(v)

self._check_parameter_dependencies(self.parameters)

self.parameters_dependencies = self._compute_parameter_dependencies(self.parameters)

def _get_counter_reference(self):
"""Identify which factory should be used for a shared counter."""
Expand Down Expand Up @@ -346,7 +347,7 @@ def _is_postgen_declaration(self, name, value):
"""Captures instances of PostGenerationDeclaration."""
return isinstance(value, declarations.PostGenerationDeclaration)

def _compute_parameter_dependencies(self, parameters):
def _check_parameter_dependencies(self, parameters):
"""Find out in what order parameters should be called."""
# Warning: parameters only provide reverse dependencies; we reverse them into standard dependencies.
# deep_revdeps: set of fields a field depend indirectly upon
Expand All @@ -368,7 +369,7 @@ def _compute_parameter_dependencies(self, parameters):
cyclic = [name for name, field_deps in deep_revdeps.items() if name in field_deps]
if cyclic:
raise errors.CyclicDefinitionError(
"Cyclic definition detected on %s' Params around %s"
"Cyclic definition detected on %r; Params around %s"
% (self.factory, ', '.join(cyclic)))
return deps

Expand Down
2 changes: 1 addition & 1 deletion factory/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def compute(self, name):
"""Actually compute the value for a given name."""
value = self.parameters[name]
if isinstance(value, declarations.Parameter):
overrides = value.compute(name, self.declaration_stack.current())
overrides = value.as_declarations(name, self.declaration_stack.current())
else:
overrides = {name: value}
self.declaration_stack['overrides'].update(overrides)
Expand Down
63 changes: 57 additions & 6 deletions factory/declarations.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class BaseDeclaration(object):
This allows them to refer to attributes defined by other BaseDeclarations
in the same factory.
"""

creation_counter = 0

def __init__(self, **kwargs):
Expand Down Expand Up @@ -443,6 +444,36 @@ def generate(self, sequence, obj, create, params):
# ==========


class UNDEFINED(object):
pass


class Maybe(BaseDeclaration):
def __init__(self, decider, yes_declaration, no_declaration=None):
self.decider = decider
self.yes = yes_declaration
self.no = no_declaration

def evaluate(self, sequence, obj, create, extra=None, containers=()):
decider = getattr(obj, self.decider, None)
target = self.yes if decider else self.no

if isinstance(target, BaseDeclaration):
return target.evaluate(
sequence=sequence,
obj=obj,
create=create,
extra=extra,
containers=containers,
)
else:
# Flat value
return target

def __repr__(self):
return 'Maybe(%r, yes=%r, no=%r)' % (self.decider, self.yes, self.no)


class Parameter(object):
"""A complex parameter, to be used in a Factory.Params section.
Expand All @@ -451,7 +482,7 @@ class Parameter(object):
- Optionally, a get_revdeps() function (to compute other parameters it may alter)
"""

def compute(self, field_name, declarations):
def as_declarations(self, field_name, declarations):
"""Compute the overrides for this parameter.
Args:
Expand All @@ -468,16 +499,36 @@ def get_revdeps(self, parameters):
return []


class SimpleParameter(Parameter):
def __init__(self, value):
self.value = value

def as_declarations(self, field_name, declarations):
return {
field_name: self.value,
}

@classmethod
def wrap(cls, value):
if not isinstance(value, Parameter):
return cls(value)
return value


class Trait(Parameter):
"""The simplest complex parameter, it enables a bunch of new declarations based on a boolean flag."""
def __init__(self, **overrides):
self.overrides = overrides

def compute(self, field_name, declarations):
if declarations.get(field_name):
return self.overrides
else:
return {}
def as_declarations(self, field_name, declarations):
overrides = {}
for maybe_field, new_value in self.overrides.items():
overrides[maybe_field] = Maybe(
decider=field_name,
yes_declaration=new_value,
no_declaration=declarations.get(maybe_field, None),
)
return overrides

def get_revdeps(self, parameters):
"""This might alter fields it's injecting."""
Expand Down

0 comments on commit c079d87

Please sign in to comment.