def __new__(mcls, name, bases, namespace_dict): my_type = super(FunctionAnchoringType, mcls).__new__(mcls, name, bases, namespace_dict) # We want the type's `vars`, but we want them "getted," and not in a # `dict`, so we'll get method objects instead of plain functions. my_getted_vars = misc_tools.getted_vars(my_type) # Repeat after me: "Getted, not dict." functions_to_anchor = [value for key, value in my_getted_vars.items() if isinstance(value, types.FunctionType) and not misc_tools.is_magic_variable_name(key)] for function in functions_to_anchor: module_name = function.__module__ module = sys.modules[module_name] function_name = function.__name__ # Since this metaclass is a hacky enough solution as it is, let's # be careful and ensure no object is already defined by the same # name in the module level: (todotest) try: already_defined_object = getattr(module, function_name) except AttributeError: # Good, there is no object defined under our anchor address. # This is the normal case. setattr(module, function_name, function) else: # Something already exists at the anchor address; let's be # careful. if already_defined_object is not function: raise Exception("An object `%s.%s` already exists! Can't " "anchor function." % \ (module_name, function_name)) return my_type
def __new__(mcls, name, bases, namespace_dict): my_type = super(FunctionAnchoringType, mcls).__new__(mcls, name, bases, namespace_dict) # We want the type's `vars`, but we want them "getted," and not in a # `dict`, so we'll get method objects instead of plain functions. my_getted_vars = misc_tools.getted_vars(my_type) # Repeat after me: "Getted, not dict." functions_to_anchor = [ value for key, value in my_getted_vars.items() if isinstance(value, types.FunctionType) and not misc_tools.is_magic_variable_name(key) ] for function in functions_to_anchor: module_name = function.__module__ module = sys.modules[module_name] function_name = function.__name__ # Since this metaclass is a hacky enough solution as it is, let's # be careful and ensure no object is already defined by the same # name in the module level: (todotest) try: already_defined_object = getattr(module, function_name) except AttributeError: # Good, there is no object defined under our anchor address. # This is the normal case. setattr(module, function_name, function) else: # Something already exists at the anchor address; let's be # careful. if already_defined_object is not function: raise Exception("An object `%s.%s` already exists! Can't " "anchor function." % \ (module_name, function_name)) return my_type
def __init_analysis(self): '''Analyze the simpack.''' simpack = self.simpack try: State = simpack.State except AttributeError: raise InvalidSimpack("The `%s` simpack does not define a `State` " "class." % simpack.__name__.rsplit('.')[-1]) if not misc_tools.is_subclass(State, garlicsim.data_structures.State): raise InvalidSimpack("The `%s` simpack defines a `State` class, " "but it's not a subclass of " "`garlicsim.data_structures.State`." % \ simpack.__name__.rsplit('.')[-1]) state_methods = dict( (name, value) for (name, value) in list(misc_tools.getted_vars(State).items()) if isinstance(value, collections.Callable) ) self.step_functions_by_type = dict((step_type, []) for step_type in step_types.step_types_list) '''dict mapping from each step type to step functions of that type.''' for method in list(state_methods.values()): step_type = StepType.get_step_type(method) if step_type: self.step_functions_by_type[step_type].append(method) if self.step_functions_by_type[step_types.HistoryStep] or \ self.step_functions_by_type[step_types.HistoryStepGenerator]: self.history_dependent = True self.all_step_functions = ( self.step_functions_by_type[step_types.HistoryStepGenerator] + self.step_functions_by_type[step_types.HistoryStep] ) if (self.step_functions_by_type[step_types.SimpleStep] or self.step_functions_by_type[step_types.StepGenerator] or self.step_functions_by_type[step_types.InplaceStep] or self.step_functions_by_type[step_types.InplaceStepGenerator]): raise InvalidSimpack("The `%s` simpack is defining both a " "history-dependent step and a " "non-history-dependent step - which " "is forbidden." % \ simpack.__name__.rsplit('.')[-1]) else: # No history step defined self.history_dependent = False self.all_step_functions = ( self.step_functions_by_type[step_types.StepGenerator] + \ self.step_functions_by_type[step_types.SimpleStep] + \ self.step_functions_by_type[step_types.InplaceStepGenerator] +\ self.step_functions_by_type[step_types.InplaceStep] ) # (no-op assignments, just for docs:) self.history_dependent = self.history_dependent '''Flag saying whether the simpack looks at previous states.''' self.all_step_functions = self.all_step_functions ''' All the step functions that the simpack provides, sorted by priority. ''' if not self.all_step_functions: raise InvalidSimpack("The `%s` simpack has not defined any kind " "of step function." % \ simpack.__name__.rsplit('.')[-1]) self.default_step_function = self.all_step_functions[0] '''
def __init_analysis(self): '''Analyze the simpack.''' simpack = self.simpack try: State = simpack.State except AttributeError: raise InvalidSimpack("The `%s` simpack does not define a `State` " "class." % simpack.__name__.rsplit('.')[-1]) if not misc_tools.is_subclass(State, garlicsim.data_structures.State): raise InvalidSimpack("The `%s` simpack defines a `State` class, " "but it's not a subclass of " "`garlicsim.data_structures.State`." % \ simpack.__name__.rsplit('.')[-1]) state_methods = dict( (name, value) for (name, value) in misc_tools.getted_vars(State).iteritems() if callable(value)) self.step_functions_by_type = dict( (step_type, []) for step_type in step_types.step_types_list) '''dict mapping from each step type to step functions of that type.''' for method in state_methods.itervalues(): step_type = StepType.get_step_type(method) if step_type: self.step_functions_by_type[step_type].append(method) if self.step_functions_by_type[step_types.HistoryStep] or \ self.step_functions_by_type[step_types.HistoryStepGenerator]: self.history_dependent = True self.all_step_functions = ( self.step_functions_by_type[step_types.HistoryStepGenerator] + self.step_functions_by_type[step_types.HistoryStep]) if (self.step_functions_by_type[step_types.SimpleStep] or self.step_functions_by_type[step_types.StepGenerator] or self.step_functions_by_type[step_types.InplaceStep] or self.step_functions_by_type[ step_types.InplaceStepGenerator]): raise InvalidSimpack("The `%s` simpack is defining both a " "history-dependent step and a " "non-history-dependent step - which " "is forbidden." % \ simpack.__name__.rsplit('.')[-1]) else: # No history step defined self.history_dependent = False self.all_step_functions = ( self.step_functions_by_type[step_types.StepGenerator] + \ self.step_functions_by_type[step_types.SimpleStep] + \ self.step_functions_by_type[step_types.InplaceStepGenerator] +\ self.step_functions_by_type[step_types.InplaceStep] ) # (no-op assignments, just for docs:) self.history_dependent = self.history_dependent '''Flag saying whether the simpack looks at previous states.''' self.all_step_functions = self.all_step_functions ''' All the step functions that the simpack provides, sorted by priority. ''' if not self.all_step_functions: raise InvalidSimpack("The `%s` simpack has not defined any kind " "of step function." % \ simpack.__name__.rsplit('.')[-1]) self.default_step_function = self.all_step_functions[0] '''