def __init__(self, **kwargs): attr.attrs( these=dict( raw_=attr.attrib(default=undefined), **dict((field.attr_name, attr.attrib( default=getattr(field, "default", undefined))) for field in fields().values())), cmp=False, slots=True, frozen=True, )(cls) return cls.__init__(self, **kwargs)
def wrap(cls): attrs_fn = attrs(auto_attribs=True, *args, **kwargs) attr_cls = attrs_fn(cls) anno_attr_cls = annotate_init(attr_cls) inj_cls = inject_init(anno_attr_cls) return inj_cls
def wrap(cls): attr_cls = attr.attrs(cls, repr=False) builder = _ProcessBuilder(attr_cls) builder.add_properties() if autodoc: builder.render_docstrings() setattr(attr_cls, "__xsimlab_cls__", builder.build_class()) return attr_cls
def decorator(cls): attrs_kwargs = {'kw_only': True, **kwargs} cls = attr.attrs(cls, **attrs_kwargs) if order: for element_name in order: if not hasattr(getattr(cls, '__attrs_attrs__'), element_name): raise AssertionError( "order element '{}' not declared in model".format( element_name)) cls.__paxb_attrs__ = (name, ns, ns_map, order) return cls
def __call__(self, cls): known_keys = [] # add type checking converters to attribs before running through # attr.attrs() for key, attrib in cls.__dict__.items(): if hasattr(attrib, "_default") and hasattr(attrib, "converter"): if attrib._default == attr.NOTHING: attrib._default = converters.UNSET_REQUIRED_VALUE # wrap any validator in one that includes the key in the error # message if attrib._validator is not None: attrib._validator = WrappedValidator( self._full_key(key), attrib._validator) if attrib.type is not None: attrib.converter = converters.Converters.for_type( attrib.type, self._full_key(key)) else: attrib.converter = converters.ConfigValueConverter( self._full_key(key)).validate known_keys.append(key) # now we can let attrs work its magic attrib_cls = attr.attrs(cls) # lastly we'll replace the __init__ provided by attrs (which accepts # arguments directly) with one that accepts a dict along with # additional kargs, merges and cleans it up before passing it to attrs original_init = attrib_cls.__init__ # need to alias self so we don't confuse the decorated class with this # decorator class! me = self def init_from_dict(self, config_dict={}, **extra_kwargs): original_init( self, **me._prepare_config_dict(known_keys, config_dict, **extra_kwargs)) if hasattr(self, "__config_post_init__"): self.__config_post_init__(config_dict) attrib_cls.__init__ = init_from_dict attrib_cls.from_values = original_init return attrib_cls
def _attrify_class(cls): """Return a `cls` after having passed through :func:`attr.attrs`. This pulls out and converts `attr.ib` declared as class attributes into :class:`attr.Attribute` objects and it also adds dunder-methods such as `__init__`. The following instance attributes are also defined with None or empty values (proper values will be set later at model creation): __xsimlab_model__ : obj :class:`Model` instance to which the process instance is attached. __xsimlab_name__ : str Name given for this process in the model. __xsimlab_store__ : dict or object Simulation data store. __xsimlab_store_keys__ : dict Dictionary that maps variable names to their corresponding key (or list of keys for group variables) in the store. Such keys consist of pairs like `('foo', 'bar')` where 'foo' is the name of any process in the same model and 'bar' is the name of a variable declared in that process. __xsimlab_od_keys__ : dict Dictionary that maps variable names to the location of their target on-demand variable (or a list of locations for group variables). Locations are tuples like store keys. """ def init_process(self): self.__xsimlab_model__ = None self.__xsimlab_name__ = None self.__xsimlab_store__ = None self.__xsimlab_store_keys__ = {} self.__xsimlab_od_keys__ = {} setattr(cls, '__attrs_post_init__', init_process) return attr.attrs(cls)
def __call__(self, f): return attr.attrs(*self.args, **self.kwargs)(f)
if raw: return result result = json.loads(escape_ansi(result)) if result else {} if result.get('success', False): print('Pass') elif result.get('error'): print('Conda error: {}'.format(result.get('error'))) return result def get_python_command(self, extra=()): return CommandSequence(self.source, self.pip.get_python_command(extra=extra)) # enable hashing with cmp=False because pdb fails on unhashable exceptions exception = attrs(str=True, cmp=False) @exception class CondaException(Exception, NonStrictAttrs): command = attrib() message = attrib(default=None) @exception class UnknownCondaError(CondaException): data = attrib(default=Factory(dict)) @exception class PackagesNotFoundError(CondaException):
def create_component(cls): attr_cls = attr.attrs(cls, repr=False) vars_dict = _create_variables_dict(attr_cls) forcing_dict = _create_forcing_dict(cls, vars_dict) new_cls = _create_new_cls(cls, _create_xsimlab_var_dict(vars_dict), init_stage) def flux_decorator(self, func): """ flux function decorator to unpack arguments """ @wraps(func) def unpack_args(**kwargs): state = kwargs.get('state') parameters = kwargs.get('parameters') forcings = kwargs.get('forcings') if kwargs.get('vectorized'): vectorized = kwargs.pop('vectorized') else: vectorized = False input_args = {} args_vectorize_exclude = [] args_signature_input = [] args_signature_output = [] signaturize = False _dims = kwargs.get('dims') if isinstance(_dims, tuple): args_signature_output.append(f"{'(' + ','.join(_dims) + ')'}") else: args_signature_output.append(f"({_dims})") for v_dict in self.flux_input_args['vars']: if isinstance(v_dict['label'], list) or isinstance(v_dict['label'], np.ndarray): input_args[v_dict['var']] = [state[label] for label in v_dict['label']] args_signature_input.append('(list_dims)') args_signature_output.append('(list_dims)') else: input_args[v_dict['var']] = state[v_dict['label']] if v_dict['dim'] is None: args_signature_input.append("()") elif isinstance(v_dict['dim'], tuple): args_signature_input.append(f"{'(' + ','.join(v_dict['dim']) + ')'}") else: args_signature_input.append(f"{'(' + str(v_dict['dim']) + ')'}") for v_dict in self.flux_input_args['list_input_vars']: input_args[v_dict['var']] = np.concatenate([state[label] for label in v_dict['label']], axis=None) args_signature_input.append('(list)') signaturize = True for v_dict in self.flux_input_args['group_args']: if vectorized: group_arg = [state[label] for label in v_dict['label']] if len(group_arg) == 1: input_args[v_dict['var']] = group_arg[0] else: max_arg_len = max([np.size(items) for items in group_arg]) _input_args = [] for arg in group_arg: if np.size(arg) != max_arg_len: _input_args.append(np.concatenate([arg for i in range(max_arg_len)], axis=None)) else: _input_args.append(arg) _input_args = np.array(_input_args) input_args[v_dict['var']] = _input_args try: add_dim = np.shape(_input_args)[1] except: add_dim = 0 if add_dim > 1: if v_dict['dim']: if isinstance(v_dict['dim'], tuple): vars_sig = f"{'(' + ','.join(v_dict['dim']) + ',n)'}" else: vars_sig = f"{'(' + v_dict['dim'] + ',n)'}" args_signature_input.append(vars_sig) else: args_signature_input.append('(list)') signaturize = True else: args_vectorize_exclude.append(v_dict['var']) signaturize = True else: states = [state[label] for label in v_dict['label']] if len(states) == 1: # unpack list to array, for easier handling of single group arg input_args[v_dict['var']] = states[0] else: input_args[v_dict['var']] = [state[label] for label in v_dict['label']] args_vectorize_exclude.append(v_dict['var']) signaturize = False for p_dict in self.flux_input_args['pars']: if p_dict['dim']: if isinstance(p_dict['dim'], tuple): args_signature_input.append(f"{'(' + ','.join(p_dict['dim']) + ')'}") else: args_signature_input.append(f"{'(' + str(p_dict['dim']) + ')'}") input_args[p_dict['var']] = parameters[p_dict['label']] signaturize = True else: args_signature_input.append(str(p_dict['dim'])) input_args[p_dict['var']] = parameters[p_dict['label']] for f_dict in self.flux_input_args['forcs']: input_args[f_dict['var']] = forcings[f_dict['label']] args_vectorize_exclude.append(f_dict['var']) signaturize = False if not _dims: vectorized = False if vectorized: if signaturize: print("signaturizing") if not args_signature_output: args_signature_output.append('()') signature = f"(),{','.join(args_signature_input)}->{','.join(args_signature_output)}" try: return np.vectorize(func, excluded=args_vectorize_exclude, signature=signature )(self, **input_args) except AttributeError: return np.vectorize(func, excluded=args_vectorize_exclude)(self, **input_args) else: return np.vectorize(func, excluded=args_vectorize_exclude)(self, **input_args) else: return func(self, **input_args) return unpack_args def initialize(self): """ """ super(new_cls, self).initialize() print(f"Initializing component {self.label}") _initialize_process_vars(self, vars_dict) self.flux_input_args = _create_flux_inputargs_dict(self, vars_dict) _initialize_fluxes(self, vars_dict) _initialize_forcings(self, forcing_dict) setattr(new_cls, 'flux_decorator', flux_decorator) setattr(new_cls, 'initialize', initialize) process_cls = xs.process(new_cls) # allow passing helper functions through to process class _forcing_input_functions = [value.__name__ for value in forcing_dict.values()] cls_dir = dir(cls) for attribute in cls_dir: if hasattr(cls, attribute) and callable(getattr(cls, attribute)): if not attribute.startswith("__") and attribute not in _forcing_input_functions: print("setting new attr method") print(attribute) setattr(process_cls, attribute, getattr(cls, attribute)) return process_cls
def _decorate(klass): klass = attr.attrs(klass) klass.validate = _validate return klass
def wrap(cls): return attrs(cls)
def wrap(cls): return attrs(cls, frozen=True, slots=True)
def wrap(cls): wrapped = attrs(cls) wrapped.__related_strict__ = strict return wrapped
def wrap(cls): wrapped = attrs(cls, frozen=True, slots=True) wrapped.__related_strict__ = strict return wrapped
def decorator(cls): cls = attr.attrs(*args, **kwargs)(cls) starrify_class(cls) return cls