def check_config(self, config, c_args, **kwargs): """ Uses the config schema valid_configs to validate config arguments. A leading '0_' indicates that the argument is permitted to be None. :param config: a configuration entry :param c_args: a tuple of args :param kwargs: :return: """ vc = valid_configs[config] if len(c_args) != vc.nargs: raise ValueError( 'Wrong number of arguments (%d supplied; %d required)' % (len(c_args), vc.nargs)) for i, t in enumerate(vc.argtypes): if t.startswith('0_'): if c_args[i] is None: continue t = t.split('_')[1] if t == 'hint': if c_args[i] in ('context', 'flowable', 'quantity'): continue elif t == 'float': if isinstance(c_args[i], float) or isinstance(c_args[i], int): continue elif t == 'str': if isinstance(c_args[i], str): continue elif t == 'direction': try: check_direction(c_args[i]) except KeyError: raise ValueError( 'Argument %d [%s] is not a valid direction' % (i, c_args[i])) continue elif t == 'context': # check to ensure t is a recognized locally defined context cx = self._archive.tm[c_args[i]] if cx is None: raise ValueError( 'Argument %d [%s] is not a recognized local context' % (i, c_args[i])) continue else: ''' if not isinstance(c_args[i], str): raise TypeError('%s [%d:%s]: Configuraton arguments must be strings and not entities' % (config, i, c_args[i])) ''' e = self._archive.retrieve_or_fetch_entity(c_args[i]) if e.entity_type == t: continue raise TypeError('Argument %d should be type %s' % (i, t)) return True
def emitters(self, flow, direction=None, context=None, **kwargs): self.check_bg() if context is not None: context = self._index.get_context(context) if direction is not None: direction = check_direction(direction) for x in self._flat.emitters(flow, direction, context): yield self._exchange_from_term_ref(x)
def _create_fragment(flow, direction, uuid=None, parent=None, name=None, comment=None, value=None, balance=False, **kwargs): """ :param flow: :param direction: :param uuid: :param parent: :param name: :param comment: :param value: :param balance: :param kwargs: :return: """ direction = check_direction(direction) if name is None: name = flow['Name'] name = kwargs.pop('Name', name) if comment is None: comment = '' comment = kwargs.pop('Comment', comment) if parent is None: if value is None: value = 1.0 if uuid is None: frag = LcFragment.new(name, flow, direction, Comment=comment, exchange_value=value, **kwargs) else: frag = LcFragment(uuid, flow, direction, Comment=comment, exchange_value=value, Name=name, **kwargs) else: if parent.term.is_null: parent.to_foreground() else: parent.unset_background() if balance or parent.term.is_subfrag: # exchange value set during traversal value = None if uuid is None: frag = LcFragment.new(name, flow, direction, parent=parent, Comment=comment, exchange_value=value, balance_flow=balance, **kwargs) else: frag = LcFragment(uuid, flow, direction, parent=parent, Comment=comment, exchange_value=value, balance_flow=balance, Name=name, **kwargs) # traverse -- may not need to do this anymore if we switch to live traversals for everything # parent.traverse(None) # in fact, let's skip it # this cannot be done internally-- really we need create_fragment_from_exchange to do this # if flow.context.elementary: # frag.terminate(flow.context) return frag
def direction(self, value): if value is None: # this is the default: should set the direction by the reference. Only non-none if from_json if self.is_process and self.valid: rx = self.term_node.reference(self.term_flow) value = rx.direction else: # for fg, invert direction doesn't make sense. for subfragments, direction is ignored value = comp_dir(self._parent.direction) self._direction = check_direction(value)
def remove_reference(self, flow, dirn): dirn = check_direction(dirn) k = (flow.external_ref, dirn) rx = self._reference_entity[k] if rx.key in self._exchanges: raise DuplicateExchangeError(rx) self._reference_entity.pop(k) rx.unset_ref(self) self.remove_allocation(rx) self._exchanges[rx.key] = rx if self._alloc_by_quantity is not None: self.allocate_by_quantity(self._alloc_by_quantity)
def set_reference(self, flow, dirn): """ Exchange must already exist. fmr: If the exchange is currently terminated, the termination is removed. now: exchanges terminated to non-elementary context are now allowed :param flow: :param dirn: :return: """ # self._strip_term(flow, dirn) dirn = check_direction(dirn) if (flow.external_ref, dirn) in self._reference_entity: # already a reference return self._reference_entity[flow.external_ref, dirn] else: rx = list(self._gen_exchanges(flow, dirn, reference=False)) if len(rx) == 0: raise NoExchangeFound(flow, dirn) elif len(rx) > 1: raise AmbiguousReferenceError(rx) else: self._set_reference(rx[0]) return rx[0]
def add_exchange(self, flow, dirn, reference=None, value=None, termination=None, add_dups=False): """ This is used to create Exchanges and ExchangeValues and AllocatedExchanges. If the flow+dir+term is already in the exchange set: if no reference is specified and/or no value is specified- nothing to do otherwise (if reference and value are specified): upgrade the exchange to an allocatedExchange and add the new reference exch val otherwise: if reference is specified, create an AllocatedExchange otherwise create an Exchange / ExchangeValue :param flow: :param dirn: :param reference: :param value: :param termination: None for reference or cutoff flows; a context for elementary flows; a valid external_ref for terminated intermediate flows. :param add_dups: (False) set to true to handle "duplicate exchange" errors by cumulating their values :return: """ dirn = check_direction(dirn) if (flow.external_ref, dirn) in self._reference_entity: raise AlreadyAReference((flow, dirn)) _x = hash((self.external_ref, flow.external_ref, dirn, termination)) if _x in self._exchanges: if value is None or value == 0: return None e = self._exchanges[_x] if reference is None: if isinstance(value, dict): e.update(value) else: try: e.value = value # this will catch already-set errors except DuplicateExchangeError: if add_dups: e.add_to_value(value) else: print('Duplicate exchange in process %s:\n%s' % (self.external_ref, e)) raise return e else: try: e[reference] = value # this will catch already-set errors except DuplicateExchangeError: if add_dups: e.add_to_value(value, reference=reference) else: print('Duplicate exchange in process %s:\n%s' % (self.external_ref, e)) raise except ValueError: print('Error adding [%s] = %10.3g for exchange\n%s\nto process\n%s' % ( reference.flow.external_ref, value, e, self.external_ref)) raise return e else: if isinstance(value, Number) or value is None: if reference is None: e = ExchangeValue(self, flow, dirn, value=value, termination=termination) else: if reference not in self.reference_entity: raise KeyError('Specified reference is not registered with process: %s' % reference) e = ExchangeValue(self, flow, dirn, value=None, termination=termination) e[reference] = value elif isinstance(value, dict): e = ExchangeValue(self, flow, dirn, value_dict=value, termination=termination) else: raise TypeError('Unhandled value type %s' % type(value)) # This is the only point an exchange (must be ExchangeValue) is added to the process (see also _strip_term) self._exchanges[e.key] = e self._exch_map[e.flow.external_ref].add(e) return e