def __init__(self, source, limits=None): """ Initializes TransactionNode. """ if isinstance(source, type(self)): # Copy initialization: self.source = source.source self.limits = source.limits return # Hold on to the original list/dict/whatever. # (Consider copying it in case input `children` is mutated?) self.source = source # Parse `limits` input: if limits is not None: # Cast to LimitTuple if not already in that format: if not isinstance(limits, LimitTuple): limits = LimitTuple(*limits) self.limits = limits else: # To avoid testing for `self.limits is not None` elsewhere, # assign an all-None-valued LimitTuple if `limits` was not # provided. self.limits = LimitTuple() # Generate `children` attribute by recursively generating a # TransactionNode instance for each child in `source`. self.children = _children_from_source(self)
def group_default_methods(field_names=LINK_FIELD_NAMES): """ Returns methods returning sets of linked accts. as a LimitTuple. """ methods = [] # Rather than write out four separate methods that return # min_inflow_link, max_inflow_link, ..., we write a generator for # such methods and return a full set of them as a LimitTuple: for field_name in field_names: # Define a method that returns the group of linked accounts for # a given link (e.g. `max_inflow_link`). # NOTE: Use `field_name` as a default value to avoid the issue # where the closure will use the most recent value for # `field_name` rather than the value at the time the closure # was defined. (This could also be solved by using a partial). # The default value is locked in at definition time. def default_method(account, name=field_name): # Return the group for the given link if the link exists: if hasattr(account, name): link = getattr(account, name) if link is not None: return link.group # If the account doesn't have a link (either because it's # not a LinkedLimitAccount or similar, or because its link # is None), then simply return None: return None # default_method over. It will be added to the LimitTuple later. methods.append(default_method) return LimitTuple(*methods)
def transaction_default_methods(field_names=TRANSACTION_LIMIT_FIELD_NAMES): """ Returns methods for finding min/max in/outflows as a LimitTuple. """ methods = [] # Rather than write out four separate methods that return # min_inflows, max_inflows, ..., we write a generator for such # methods and return a full set of them as a LimitTuple: for field_name in field_names: # We use `field_name` as a default value to avoid the issue # where the closure will use the most recent value for # `field_name` rather than the value at the time the closure # was defined. (This could also be solved by using a partial). # The default value is locked in at definition time. methods.append(lambda account, name=field_name: getattr(account, name)) return LimitTuple(*methods)
""" Defines helper functions for identifying an account's min/max. """ from forecaster.accounts import LimitTuple # TODO: Move LimitTuple constants to forecaster.accounts module. # Consider going further and refactoring `Account` so that # `max_inflows`/etc and `max_inflow_link`/etc are held by LimitTuples # (e.g. so client code accesses `transaction_schedule.max_inflow` # or `link.max_inflow` instead). Is this pythonic? # Map LimitTuple fields to the names of AccountLink members of # LinkedLimitAccount objects: LINK_FIELD_NAMES = LimitTuple('min_inflow_link', 'max_inflow_link', 'min_outflow_link', 'max_outflow_link') # Map LimitTuple fields to the named of min/max inflow/outflow members # of Account objects: TRANSACTION_LIMIT_FIELD_NAMES = LimitTuple('min_inflows', 'max_inflows', 'min_outflows', 'max_outflows') def transaction_default_methods(field_names=TRANSACTION_LIMIT_FIELD_NAMES): """ Returns methods for finding min/max in/outflows as a LimitTuple. """ methods = [] # Rather than write out four separate methods that return # min_inflows, max_inflows, ..., we write a generator for such # methods and return a full set of them as a LimitTuple: for field_name in field_names: # We use `field_name` as a default value to avoid the issue # where the closure will use the most recent value for # `field_name` rather than the value at the time the closure # was defined. (This could also be solved by using a partial).