示例#1
0
    def __init__(self, simpack):
        self.simpack = simpack

        if isinstance(simpack, types.ModuleType):
            simpack_wx_module_name = ''.join((self.simpack.__name__, '.wx'))

        import_tools.import_if_exists(simpack_wx_module_name, silent_fail=True)
        # This imports the `wx` submodule, if it exists, but it does *not* keep
        # a reference to it. We'll access `wx` as an attribute of the simpack
        # below.

        try:
            self.simpack_wx = self.simpack.wx
        except AttributeError:
            self.simpack_wx = None
            #raise Exception("Simpack has no wx") # todo: edit this

        self.__init_analysis_settings()
示例#2
0
 def __init__(self, simpack):
     self.simpack = simpack
     
     if isinstance(simpack, types.ModuleType):
         simpack_wx_module_name = ''.join((
             self.simpack.__name__,
             '.wx'
         ))
     
     import_tools.import_if_exists(simpack_wx_module_name)
     # This imports the `wx` submodule, if it exists, but it does *not* keep
     # a reference to it. We'll access `wx` as an attribute of the simpack
     # below.
         
     try:
         self.simpack_wx = self.simpack.wx
     except AttributeError:
         self.simpack_wx = None
         #raise Exception('''Simpack has no wx''') # todo: edit this
     
     self.__init_analysis_settings()
 def __init_analysis_settings(self):
     '''Analyze the simpack to produce a Settings object.'''
     # todo: consider doing this in `Settings.__init__`
     
     # We want to access the `.settings` of our simpack, but we don't know
     # if our simpack is a module or some other kind of object. So if it's a
     # module, we'll `try` to import `settings`.
     
     self.settings = Settings(self)
     
     if isinstance(self.simpack, types.ModuleType) and \
        not hasattr(self.simpack, 'settings'):
         
         # The `if` that we did here means: "If there's reason to suspect
         # that `self.simpack.settings` is a module that exists but hasn't
         # been imported yet."
         
         settings_module_name = ''.join((
             self.simpack.__name__,
             '.settings'
         ))
         
         import_tools.import_if_exists(settings_module_name,
                                       silent_fail=True)
         # This imports the `settings` submodule, if it exists, but it
         # does *not* keep a reference to it. We'll access `settings` as
         # an attribute of the simpack below.
         
     # Checking if there are original settings at all. If there aren't,
     # we're done.
     if hasattr(self.simpack, 'settings'):
         
         original_settings = getattr(self.simpack, 'settings')
         
         for setting_name in list(list(vars(self.settings).keys())):
             if hasattr(original_settings, setting_name):
                 value = getattr(original_settings, setting_name)
                 setattr(self.settings, setting_name, value)
示例#4
0
 def __init_analysis_settings(self):
     '''Analyze the simpack_wx to produce a Settings object.'''
     # todo: consider doing this in Settings.__init__
     
     # We want to access the `.settings` of our simpack_wx, but we don't know if
     # our simpack_wx is a module or some other kind of object. So if it's a
     # module, we'll try to import `settings`.
     
     self.settings = Settings()        
     
     if isinstance(self.simpack_wx, types.ModuleType) and \
        not hasattr(self.simpack_wx, 'settings'):
         
         # The `if` that we did here means: "If there's reason to suspect
         # that self.simpack_wx.settings is a module that exists but hasn't
         # been imported yet."
             
         settings_module_name = ''.join((
             self.simpack_wx.__name__,
             '.settings'
         ))
         
         import_tools.import_if_exists(settings_module_name)
         # This imports the `settings` submodule, if it exists, but it does
         # *not* keep a reference to it. We'll access `settings` as an
         # attribute of the simpack_wx below.
         
     # Checking if there are original settings at all. If there aren't, we're
     # done.
     if self.simpack_wx and hasattr(self.simpack_wx, 'settings'):
         
         original_settings = getattr(self.simpack_wx, 'settings')
     
         for (key, value) in vars(self.settings).iteritems():
             if hasattr(original_settings, key):
                 actual_value = getattr(original_settings, key)
                 setattr(self.settings, key, actual_value)
示例#5
0
    def __init_analysis_settings(self):
        '''Analyze the simpack to produce a Settings object.'''
        # todo: consider doing this in `Settings.__init__`

        # We want to access the `.settings` of our simpack, but we don't know
        # if our simpack is a module or some other kind of object. So if it's a
        # module, we'll `try` to import `settings`.

        self.settings = Settings(self)

        if isinstance(self.simpack, types.ModuleType) and \
           not hasattr(self.simpack, 'settings'):

            # The `if` that we did here means: "If there's reason to suspect
            # that `self.simpack.settings` is a module that exists but hasn't
            # been imported yet."

            settings_module_name = ''.join(
                (self.simpack.__name__, '.settings'))

            import_tools.import_if_exists(settings_module_name,
                                          silent_fail=True)
            # This imports the `settings` submodule, if it exists, but it
            # does *not* keep a reference to it. We'll access `settings` as
            # an attribute of the simpack below.

        # Checking if there are original settings at all. If there aren't,
        # we're done.
        if hasattr(self.simpack, 'settings'):

            original_settings = getattr(self.simpack, 'settings')

            for setting_name in vars(self.settings).keys():
                if hasattr(original_settings, setting_name):
                    value = getattr(original_settings, setting_name)
                    setattr(self.settings, setting_name, value)
示例#6
0
def get_object_by_address(address, root=None, namespace={}):
    '''
    Get an object by its address.
    
    For example:
    
        >>> get_object_by_address('email.encoders')
        <module 'email.encoders' from 'c:\Python27\lib\email\encoders.pyc'>
    
    `root` is an object (usually a module) whose attributes will be looked at
    when searching for the object. `namespace` is a `dict` whose keys will be
    searched as well.    
    '''
    # todo: should know what exception this will raise if the address is bad /
    # object doesn't exist.

    if not _address_pattern.match(address):
        raise ValueError("'%s' is not a legal address." % address)

    ###########################################################################
    # Before we start, we do some pre-processing of `root` and `namespace`:   #

    # We are letting the user input (base)strings for `root` and `namespace`,
    # so if he did that, we'll get the actual objects.

    if root:
        # First for `root`:
        if isinstance(root, basestring):
            root = get_object_by_address(root)
        root_short_name = root.__name__.rsplit('.', 1)[-1]

    if namespace:
        # And then for `namespace`:
        if isinstance(namespace, basestring):
            namespace = get_object_by_address(namespace)

        parent_object, namespace_dict = _get_parent_and_dict_from_namespace(
            namespace)
    else:
        parent_object, namespace_dict = None, None

    # Finished pre-processing `root` and `namespace`.                         #
    ###########################################################################

    ###########################################################################
    # The implementation is recursive: We handle the case of a single-level
    # address, like 'email'. If we get a multi-level address (i.e. contains a
    # dot,) like 'email.encoders', we use this function twice, first to get
    # `email`, and then from it to get `email.encoders`.

    if '.' not in address:

        ### Here we solve the basic case of a single-level address: ###########
        #                                                                     #

        # Let's rule out the easy option that the requested object is the root:
        if root and (address == root_short_name):
            return root

        if parent_object:

            if isinstance(parent_object, types.ModuleType) and \
               hasattr(parent_object, '__path__'):

                # `parent_object` is a package. The wanted object may be a
                # module. Let's try importing it:

                import_tools.import_if_exists('.'.join(
                    (parent_object.__name__, address)),
                                              silent_fail=True)
                # Not keeping reference, just importing so we could get later.

        # We know we have a `namespace_dict` to take the object from, and we
        # might have a `parent_object` we can take the object from by using
        # `getattr`. We always have a `namespace_dict`, but not always a
        # `parent_object`.
        #

        # We are going to prefer to do `getattr` from `parent_object`, if one
        # exists, rather than using `namespace_dict`. This is because some
        # attributes may not be present on an object's `__dict__`, and we want
        # to be able to catch them:

        # The first place we'll try to take the object from is the
        # `parent_object`. We try this before `namespace_dict` because
        # `parent_object` may have `__getattr__` or similar magic and our
        # object might be found through that:
        if parent_object and hasattr(parent_object, address):
            return getattr(parent_object, address)

        # Next is the `namespace_dict`:
        elif namespace_dict and (address in namespace_dict):
            return namespace_dict[address]

        # Last two options:
        else:
            try:
                # It may be a built-in:
                return eval(address)
            except Exception:
                # Or a module:
                return import_tools.normal_import(address)

        #                                                                     #
        ### Finished solving the basic case of a single-level address. ########

    else:  # '.' in address

        ### If we get a composite address, we solve recursively: ##############
        #                                                                     #

        first_object_address, second_object_address = address.rsplit('.', 1)

        first_object = get_object_by_address(first_object_address,
                                             root=root,
                                             namespace=namespace)

        second_object = get_object_by_address(second_object_address,
                                              namespace=first_object)

        return second_object
示例#7
0
    def __init_general(self, simpack, frame, project=None):
        '''General initialization.'''
        
        self.frame = frame
        '''The frame that this gui project lives in.'''
        
        assert isinstance(self.frame, garlicsim_wx.Frame)
        
        if isinstance(simpack, garlicsim.misc.SimpackGrokker):
            simpack_grokker = simpack            
            simpack = simpack_grokker.simpack
        else:
            simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
            
            
        self.simpack = simpack
        '''The simpack used for this gui project.'''
        
        self.simpack_grokker = simpack_grokker
        '''The simpack grokker used for this gui project.'''
        
        self.simpack_wx_grokker = garlicsim_wx.misc.SimpackWxGrokker(simpack)
        '''The simpack_wx used for this gui project.'''
        
        self.project = project or garlicsim.Project(simpack_grokker)
        '''The project encapsulated in this gui project.'''
        
        assert isinstance(self.project, garlicsim.Project)
        

        ### If it's a new project, use `ProcessCruncher` if available: ########
        #                                                                     #
        
        if (not project): # Note this is the project given as an argument
            if (crunchers.ProcessCruncher in 
                simpack_grokker.available_cruncher_types):
                
                self.project.crunching_manager.cruncher_type = \
                    crunchers.ProcessCruncher
        #                                                                     #
        #######################################################################
            
        self.path = None
        '''The active path.'''

        self.active_node = None
        '''The node that is currently displayed onscreen.'''

        self.is_playing = False
        '''Says whether the simulation is currently playing.'''
        
        self.infinity_job = None
        '''
        The job of the playing leaf, which should be crunched to infinity.
        '''
        
        self.default_buffer = 100
        '''
        The default clock buffer to crunch from an active node.

        For the user it is called "Autocrunch".
        '''
        
        self._default_buffer_before_cancellation = None
        '''
        The value of the default buffer before buffering was cancelled.

        When buffering will be enabled again, it will be set to this value.
        '''

        self.timer_for_playing = thread_timer.ThreadTimer(self.frame)
        '''Contains the timer object used when playing the simulation.'''
        
        self.frame.Bind(thread_timer.EVT_THREAD_TIMER, self.__play_next,
                        self.timer_for_playing)

        self.defacto_playing_speed = 4
        '''The playing speed that we are actually playing in.'''
        
        self.official_playing_speed = 4
        '''
        The playing speed that we're "officially" playing in.
        
        The defacto playing speed may deviate from this.
        '''
        
        self.standard_playing_speed = 4
        '''The reference playing speed. This speed is considered "normal".'''
        
        self.last_tracked_real_time = None
        '''
        The last tracked time point (real time, not simulation), for playback.
        '''
        
        self.pseudoclock = 0
        '''
        The current pseudoclock.
        
        The pseudoclock is *something like* the clock of the current active
        node. But not exactly. We're letting the pseudoclock slide more
        smoothly from one node to its neighbor, instead of jumping. This is in
        order to make some things smoother in the program. This is also why
        it's called "pseudo".
        '''
        
        self.default_step_profile = garlicsim.misc.StepProfile(
            self.simpack_grokker.default_step_function
        )
        '''The step profile that will be used be default.'''
        
        self.step_profiles = EmittingOrderedSet(
            emitter=None,
            items=(self.default_step_profile,)
        )
        '''An ordered set of step profiles that the user may use.'''
        
        self.step_profiles_to_hues = EmittingWeakKeyDefaultDict(
            emitter=None,
            default_factory=StepProfileHueDefaultFactory(self),
        )
        '''Mapping from step profile to hue that represents it in GUI.'''
        
        self._tracked_step_profile = None
        self._temp_shell_history = None
        self._temp_shell_command_history = None
        self._job_and_node_of_recent_fork_by_crunching = None
        
        ### Setting up namespace: #############################################
        #                                                                     #
        
        self.namespace = {
            
            '__name__': '__garlicsim_shell__',
            # This will become `.__module__` of classes and functions.
            
            'f': frame, 'frame': frame,
            'gp': self, 'gui_project': self,
            'p': self.project, 'project': self.project,
            't': self.project.tree, 'tree': self.project.tree,
            'gs': garlicsim, 'garlicsim': garlicsim,
            'gs_wx': garlicsim_wx, 'garlicsim_wx': garlicsim_wx,
            'wx': wx,
            'simpack': self.simpack,
            self.simpack.__name__.rsplit('.', 1)[-1]: self.simpack,
        }
        '''Namespace that will be used in shell and other places.'''
        
        garlicsim_lib = import_tools.import_if_exists('garlicsim_lib',
                                                      silent_fail=True)
        if garlicsim_lib:
            self.namespace.update({
                'gs_lib': garlicsim_lib,
                'garlicsim_lib': garlicsim_lib,
            })
        
        #                                                                     #
        ### Finished setting up namespace. ####################################
        
            
        self.__init_emitters()
        self.__init_menu_enablings()
        
        self.emitter_system.top_emitter.emit()
def get_object_by_address(address, root=None, namespace={}):
    '''
    Get an object by its address.
    
    For example:
    
        >>> get_object_by_address('email.encoders')
        <module 'email.encoders' from 'c:\Python27\lib\email\encoders.pyc'>
    
    `root` is an object (usually a module) whose attributes will be looked at
    when searching for the object. `namespace` is a `dict` whose keys will be
    searched as well.    
    '''
    # todo: should know what exception this will raise if the address is bad /
    # object doesn't exist.
    
    if not _address_pattern.match(address):
        raise ValueError("'%s' is not a legal address." % address)
    
    ###########################################################################
    # Before we start, we do some pre-processing of `root` and `namespace`:   #
    
    # We are letting the user input (base)strings for `root` and `namespace`,
    # so if he did that, we'll get the actual objects.
    
    if root:
        # First for `root`:
        if isinstance(root, str):
            root = get_object_by_address(root)
        root_short_name = root.__name__.rsplit('.', 1)[-1]
        
    if namespace:
        # And then for `namespace`:
        if isinstance(namespace, str):
            namespace = get_object_by_address(namespace)
            
        parent_object, namespace_dict = _get_parent_and_dict_from_namespace(
            namespace
        )
    else:
        parent_object, namespace_dict = None, None
            
    if parent_object is None:
        parent_object = root
        
    # Finished pre-processing `root` and `namespace`.                         #
    ###########################################################################
    
    
    ###########################################################################
    # The implementation is recursive: We handle the case of a single-level
    # address, like 'email'. If we get a multi-level address (i.e. contains a
    # dot,) like 'email.encoders', we use this function twice, first to get
    # `email`, and then from it to get `email.encoders`.
    
    if '.' not in address:
        
        ### Here we solve the basic case of a single-level address: ###########
        #                                                                     #
        
        # Let's rule out the easy option that the requested object is the root:
        if root and (address == root_short_name):
            return root
    
        if parent_object:
                
            if isinstance(parent_object, types.ModuleType) and \
               hasattr(parent_object, '__path__'):
                                
                # `parent_object` is a package. The wanted object may be a
                # module. Let's try importing it:
                
                import_tools.import_if_exists(
                    '.'.join((parent_object.__name__, address)),
                    silent_fail=True
                )
                # Not keeping reference, just importing so we could get later.
        
        # We know we have a `namespace_dict` to take the object from, and we
        # might have a `parent_object` we can take the object from by using
        # `getattr`. We always have a `namespace_dict`, but not always a
        # `parent_object`.
        #
        
        
        # We are going to prefer to do `getattr` from `parent_object`, if one
        # exists, rather than using `namespace_dict`. This is because some
        # attributes may not be present on an object's `__dict__`, and we want
        # to be able to catch them:
        
        # The first place we'll try to take the object from is the
        # `parent_object`. We try this before `namespace_dict` because
        # `parent_object` may have `__getattr__` or similar magic and our
        # object might be found through that:
        if parent_object and hasattr(parent_object, address):
            return getattr(parent_object, address)
        
        # Next is the `namespace_dict`:
        elif namespace_dict and (address in namespace_dict):
            return namespace_dict[address]
        
        # Last two options:
        else:
            try:
                # It may be a built-in:
                return eval(address) 
            except Exception:
                # Or a module:
                return import_tools.normal_import(address)
        
        #                                                                     #
        ### Finished solving the basic case of a single-level address. ########
            
        
    else: # '.' in address
        
        ### If we get a composite address, we solve recursively: ##############
        #                                                                     #
        
        first_object_address, second_object_address = address.rsplit('.', 1)
        
        first_object = get_object_by_address(first_object_address, root=root,
                                             namespace=namespace)

        second_object = get_object_by_address(second_object_address,
                                              namespace=first_object)
        
        return second_object
示例#9
0
    def __init_general(self, simpack, frame, project=None):
        '''General initialization.'''

        self.frame = frame
        '''The frame that this gui project lives in.'''

        assert isinstance(self.frame, garlicsim_wx.Frame)

        if isinstance(simpack, garlicsim.misc.SimpackGrokker):
            simpack_grokker = simpack
            simpack = simpack_grokker.simpack
        else:
            simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)

        self.simpack = simpack
        '''The simpack used for this gui project.'''

        self.simpack_grokker = simpack_grokker
        '''The simpack grokker used for this gui project.'''

        self.simpack_wx_grokker = garlicsim_wx.misc.SimpackWxGrokker(simpack)
        '''The simpack_wx used for this gui project.'''

        self.project = project or garlicsim.Project(simpack_grokker)
        '''The project encapsulated in this gui project.'''

        assert isinstance(self.project, garlicsim.Project)

        ### If it's a new project, use `ProcessCruncher` if available: ########
        #                                                                     #

        if (not project):  # Note this is the project given as an argument
            if (crunchers.ProcessCruncher
                    in simpack_grokker.available_cruncher_types):

                self.project.crunching_manager.cruncher_type = \
                    crunchers.ProcessCruncher
        #                                                                     #
        #######################################################################

        self.path = None
        '''The active path.'''

        self.active_node = None
        '''The node that is currently displayed onscreen.'''

        self.is_playing = False
        '''Says whether the simulation is currently playing.'''

        self.infinity_job = None
        '''
        The job of the playing leaf, which should be crunched to infinity.
        '''

        self.default_buffer = 100
        '''
        The default clock buffer to crunch from an active node.

        For the user it is called "Autocrunch".
        '''

        self._default_buffer_before_cancellation = None
        '''
        The value of the default buffer before buffering was cancelled.

        When buffering will be enabled again, it will be set to this value.
        '''

        self.timer_for_playing = thread_timer.ThreadTimer(self.frame)
        '''Contains the timer object used when playing the simulation.'''

        self.frame.Bind(thread_timer.EVT_THREAD_TIMER, self.__play_next,
                        self.timer_for_playing)

        self.defacto_playing_speed = 4
        '''The playing speed that we are actually playing in.'''

        self.official_playing_speed = 4
        '''
        The playing speed that we're "officially" playing in.
        
        The defacto playing speed may deviate from this.
        '''

        self.standard_playing_speed = 4
        '''The reference playing speed. This speed is considered "normal".'''

        self.last_tracked_real_time = None
        '''
        The last tracked time point (real time, not simulation), for playback.
        '''

        self.pseudoclock = 0
        '''
        The current pseudoclock.
        
        The pseudoclock is *something like* the clock of the current active
        node. But not exactly. We're letting the pseudoclock slide more
        smoothly from one node to its neighbor, instead of jumping. This is in
        order to make some things smoother in the program. This is also why
        it's called "pseudo".
        '''

        self.default_step_profile = garlicsim.misc.StepProfile(
            self.simpack_grokker.default_step_function)
        '''The step profile that will be used be default.'''

        self.step_profiles = EmittingOrderedSet(
            emitter=None, items=(self.default_step_profile, ))
        '''An ordered set of step profiles that the user may use.'''

        self.step_profiles_to_hues = EmittingWeakKeyDefaultDict(
            emitter=None,
            default_factory=StepProfileHueDefaultFactory(self),
        )
        '''Mapping from step profile to hue that represents it in GUI.'''

        self._tracked_step_profile = None
        self._temp_shell_history = None
        self._temp_shell_command_history = None
        self._job_and_node_of_recent_fork_by_crunching = None

        ### Setting up namespace: #############################################
        #                                                                     #

        self.namespace = {
            '__name__': '__garlicsim_shell__',
            # This will become `.__module__` of classes and functions.
            'f': frame,
            'frame': frame,
            'gp': self,
            'gui_project': self,
            'p': self.project,
            'project': self.project,
            't': self.project.tree,
            'tree': self.project.tree,
            'gs': garlicsim,
            'garlicsim': garlicsim,
            'gs_wx': garlicsim_wx,
            'garlicsim_wx': garlicsim_wx,
            'wx': wx,
            'simpack': self.simpack,
            self.simpack.__name__.rsplit('.', 1)[-1]: self.simpack,
        }
        '''Namespace that will be used in shell and other places.'''

        garlicsim_lib = import_tools.import_if_exists('garlicsim_lib',
                                                      silent_fail=True)
        if garlicsim_lib:
            self.namespace.update({
                'gs_lib': garlicsim_lib,
                'garlicsim_lib': garlicsim_lib,
            })

        #                                                                     #
        ### Finished setting up namespace. ####################################

        self.__init_emitters()
        self.__init_menu_enablings()

        self.emitter_system.top_emitter.emit()