Changeset 137


Ignore:
Timestamp:
07/23/2009 05:35:58 PM (13 years ago)
Author:
marcus
Message:
  • shell initialization moved from mandantory init to init_shell (options)
  • disabled command "caching" (weird import problems vanished)
  • improved event manager (class based events, blocking)
  • event controlled update of sh's trace structures
Location:
SHX/trunk/src/SeismicHandler
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • SHX/trunk/src/SeismicHandler/config/__init__.py

    r131 r137  
    1 # -*- coding: utf-8 -*- 
    2 # 
    3 # Copyright (C) 2008-2010 Marcus Walther (walther@szgrf.bgr.de) 
    4 # 
    5 # This file is part of Seismic Handler eXtended (SHX) 
    6 # Full details can be found at project website http://www.seismic-handler.org/ 
    7 #  
    8 # SHX is free software; you can redistribute it and/or modify 
    9 # it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by 
    10 # the Free Software Foundation; either version 3 of the License, or 
    11 # (at your option) any later version. 
    12 # 
    13 # SHX is distributed in the hope that it will be useful, 
    14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 
    15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    16 # GNU Lesser General Public License for more details. 
    17 # 
    18 # You should have received a copy of the GNU Lesser General Public License 
    19 # along with SHX (see license.txt); if not, write to the Free Software 
    20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
    21  
    22 """start python shell adopted to seismic handler style""" 
    23  
    24 import sys 
    25 import os 
    26 import textwrap 
    27 from SeismicHandler.core.log import logging 
    28  
    29 # change prompt style 
    30 sys.ps1 = "|shx> " 
    31 sys.ps2 = "..... " 
    32  
    33 # enable history 
    34 try: 
    35     import readline 
    36 except ImportError: 
    37     logging.debug("history not available") 
    38 else: 
    39     import atexit 
    40     import rlcompleter 
    41  
    42     historyPath = os.path.expanduser("~/.sh_history") 
    43  
    44     # function called at exit -> import necessary   
    45     def save_history(historyPath=historyPath): 
    46         import readline 
    47         readline.write_history_file(historyPath) 
    48  
    49     if os.path.exists(historyPath): 
    50         readline.read_history_file(historyPath) 
    51  
    52     atexit.register(save_history) 
    53  
    54     del atexit, readline, rlcompleter, save_history, historyPath 
    55  
    56 # print greeting and licence 
    57 from SeismicHandler.core.codes import LICENCE, VERSION 
    58 print "\n", textwrap.fill(textwrap.dedent(LICENCE % VERSION), 75).strip(), "\n" 
    59  
    60 # clean up 
    61 del sys, os, textwrap 
  • SHX/trunk/src/SeismicHandler/core/commands/__init__.py

    r127 r137  
    2727    commands = {} 
    2828     
    29     def __new__(type, *args, **kwargs): 
     29    def __new__(cls, *args, **kwargs): 
    3030        """ensure single instance""" 
    3131         
    32         if not '_the_instance' in type.__dict__: 
    33             type._the_instance = object.__new__(type) 
     32        if not '_the_instance' in cls.__dict__: 
     33            cls._the_instance = object.__new__(cls) 
    3434             
    35         return type._the_instance 
     35        return cls._the_instance 
    3636 
    3737    def __init__(self): 
  • SHX/trunk/src/SeismicHandler/core/commands/quit.py

    r127 r137  
    2222from SeismicHandler.core.log import logging 
    2323from SeismicHandler.core.shlib import shlib 
    24 from SeismicHandler.core.modules import Command 
     24from SeismicHandler.core.modules.Command import Command 
    2525 
    2626class Quit(Command): 
  • SHX/trunk/src/SeismicHandler/core/commands/run.py

    r127 r137  
    2222from SeismicHandler.core.log import logging 
    2323from SeismicHandler.core.shlib import shlib 
    24 from SeismicHandler.core.modules import Command 
     24from SeismicHandler.core.modules.Command import Command 
    2525 
    2626from StringIO import StringIO 
  • SHX/trunk/src/SeismicHandler/core/commands/startsh.py

    r127 r137  
    2222from SeismicHandler.core.log import logging 
    2323from SeismicHandler.core.shlib import shlib 
    24 from SeismicHandler.core.modules import Command 
     24from SeismicHandler.core.modules.Command import Command 
    2525 
    2626class Startsh(Command): 
  • SHX/trunk/src/SeismicHandler/core/log.py

    r127 r137  
    55# This file is part of Seismic Handler eXtended (SHX) 
    66# Full details can be found at project website http://www.seismic-handler.org/ 
    7 #  
     7# 
    88# SHX is free software; you can redistribute it and/or modify 
    99# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by 
     
    2828    logging = None 
    2929 
    30     def __new__(type, *args, **kwargs): 
     30    def __new__(cls, *args, **kwargs): 
    3131        """ensure single instance""" 
    3232 
    33         if not '_the_instance' in type.__dict__: 
    34             type._the_instance = object.__new__(type) 
     33        if not '_the_instance' in cls.__dict__: 
     34            cls._the_instance = object.__new__(cls) 
    3535 
    36         return type._the_instance 
     36        return cls._the_instance 
    3737 
    3838    def __init__(self): 
     
    4747                # assume linux system 
    4848                dir = "/tmp/" 
     49 
     50            # add more levels 
     51            # works only for root logger, not for children from getLogger() 
     52            newlvl = { 
     53                   "DEBUG2": logging.DEBUG + 1, 
     54                   } 
     55 
     56            for lvl in newlvl: 
     57                logging.addLevelName(lvl, newlvl[lvl]) 
     58                setattr(logging, lvl.lower(), lambda *args: logging.log(newlvl[lvl], *args)) 
    4959 
    5060            try: 
  • SHX/trunk/src/SeismicHandler/core/modules/Command.py

    r131 r137  
    3232from SeismicHandler.core.log import logging 
    3333from SeismicHandler.core.shlib import shlib 
    34 from  SeismicHandler.core.modules.Events import EventManager 
     34from  SeismicHandler.core.modules.Events import EventManager, Event 
    3535 
    3636class Command(object): 
     
    7575            self.promote() 
    7676 
    77         EventManager.trigger(EventManager.COMMANDRUN) 
     77        EventManager.trigger(Event(EventManager.COMMANDRUN)) 
    7878 
    7979    def Cancel(self): 
  • SHX/trunk/src/SeismicHandler/core/modules/Events.py

    r131 r137  
    2020# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
    2121 
    22 """ Events class 
     22"""Events class 
    2323 
    2424    - simple event manager 
     
    3535        return "notifier must be callable!" 
    3636 
     37class Event(object): 
     38    """Event class. 
     39 
     40    Implemented as multiton, so that equal id's are represented by identical 
     41    instances. 
     42    """ 
     43 
     44    _instances = {} 
     45 
     46    def __new__(cls, id): 
     47        if not id in cls._instances.keys(): 
     48            cls._instances[id] = object.__new__(cls, id) 
     49 
     50        return cls._instances[id] 
     51 
     52    def __init__(self, id): 
     53        self.name = id 
     54        self.done = False 
     55 
    3756class Events(object): 
     57    """Events manager 
     58 
     59    Subscribing to events: 
     60    >>> def x(e, x): print x*2 
     61    >>> e = Events() 
     62    >>> foo = Event("foo") 
     63    >>> bar = Event("bar") 
     64    >>> e.subscribe(foo, x) 
     65    >>> e.subscribe(bar, x) 
     66    >>> sorted([i.name for i in e.events]) 
     67    ['bar', 'foo'] 
     68    >>> e.events[bar] #doctest: +ELLIPSIS 
     69    [<function x at 0x...] 
     70    >>> e.events[foo] #doctest: +ELLIPSIS 
     71    [<function x at 0x...] 
     72 
     73    Now trigger an event: 
     74    >>> e.trigger(foo, 2) 
     75    4 
     76    >>> e.trigger(bar, 7) 
     77    14 
     78 
     79    Events can be blocked to prevent propagation: 
     80    >>> e.block(foo) 
     81    >>> e.trigger(foo, 2) 
     82    >>> e.trigger(foo, 4) 
     83 
     84    If an event is unblocked, pending events can be processed then or discarded. 
     85    Running only the last one is default, None skips processing in total. Here 
     86    we run all pending events with their associated data: 
     87    >>> e.unblock(foo, process="all") 
     88    4 
     89    8 
     90 
     91    Now only the last event queued: 
     92    >>> e.block(foo) 
     93    >>> e.trigger(foo, 3) 
     94    >>> e.trigger(foo, 5) 
     95    >>> e.unblock(foo) 
     96    10 
     97 
     98    A function can be unsubscribed from an event: 
     99    >>> e.unsubscribe(x, foo) 
     100    >>> e.trigger(foo, 111) 
     101    >>> e.trigger(bar, 6) 
     102    12 
     103 
     104    To unsubscribe a function in total, you don't have to know which 
     105    subscriptions are active: 
     106    >>> e.unsubscribe(x) 
     107    >>> e.trigger(foo, 99) 
     108    >>> e.trigger(bar, 6) 
     109    """ 
     110 
    38111    TRACEUPDATE = "traceupdate" 
    39112    REDRAW = "redraw" 
    40113    COMMANDRUN = "cmdrun" 
    41114 
     115    events = {} 
     116    blocked = set() 
     117    queue = [] 
     118 
    42119    def __init__(self): 
    43         self.events = {} 
    44         self.logger = logging.getLogger("core.modules.events") 
     120        self.logger = logging.getLogger("modules.events") 
    45121 
    46122    def subscribe(self, events, notify): 
    47         """ subscribe to events list 
     123        """subscribe to events list 
    48124 
    49125            - notify must contain a call back function 
     
    53129            raise NotifierNotCallableError 
    54130 
    55         # change type to list 
    56         if type(events) == str: 
     131        # change type to list if not iterable 
     132        if not hasattr(events, "__iter__"): 
    57133            events = [events, ] 
    58134 
     
    63139                self.events[e] = [notify] 
    64140 
    65             self.logger.debug("'%s' subscribed to event '%s'." % (notify, e)) 
     141            self.logger.debug("'%s' subscribed to event '%s'." % (notify, e.name)) 
    66142 
    67143    def trigger(self, event, *data): 
    68         """ trigger event """ 
    69  
    70         self.logger.debug("Event '%s' triggered." % event) 
     144        """trigger event """ 
     145 
     146        if event in self.blocked: 
     147            # save blocked event for later use 
     148            self.queue.append([event, data]) 
     149            self.logger.debug("Event '%s' triggered (but blocked)." % event.name) 
     150            return 
     151 
     152        self.logger.debug("Event '%s' triggered." % event.name) 
    71153 
    72154        if not self.events.has_key(event): 
    73             self.logger.debug("Event '%s' not found." % event) 
     155            self.logger.debug("Event '%s' not found." % event.name) 
    74156            return False 
    75157 
    76158        for i in self.events[event]: 
    77             i(*data) 
     159            i(event, *data) 
     160 
     161            # notified function has the possibility to stop further processing 
     162            if event.done: 
     163                self.logger.debug("Event '%s' propagation stopped by %s." % (event.name, i)) 
     164                break 
    78165 
    79166    def unsubscribe(self, notify, events=None): 
    80         """ unsubscribe notifier from events """ 
    81  
    82         if type(events) == str: 
    83             events = [events, ] 
     167        """unsubscribe notifier from events """ 
    84168 
    85169        if not events: 
    86170            events = self.events 
     171 
     172        if not hasattr(events, "__iter__"): 
     173            events = [events, ] 
    87174 
    88175        for e in events: 
    89176            if notify in self.events[e]: 
    90177                try: 
    91                     self.logger.debug("'%s' unsubscribed from event '%s'." % (notify, e)) 
     178                    self.logger.debug("'%s' unsubscribed from event '%s'." % (notify, e.name)) 
    92179                    self.events[e].remove(notify) 
    93180                except (ValueError): 
    94181                    pass 
    95182 
     183    def block(self, event): 
     184        """set event on block stage, this means, that the event won't be propagated 
     185        """ 
     186 
     187        self.blocked.update([event]) 
     188 
     189    def unblock(self, event, process="last"): 
     190        """unblock event propagation 
     191 
     192            @param process: 
     193                control what to do with pending events: 
     194                None   - discard 
     195                "last" - only trigger last one 
     196                "all"  - trigger all 
     197        """ 
     198 
     199        # unblock event 
     200        try: 
     201            self.blocked.remove(event) 
     202        except KeyError: 
     203            return 
     204 
     205        # check if event occurred and maybe trigger it 
     206        # work on a copy of queue 
     207        if process == "last": 
     208            # reverse order 
     209            cqueue = self.queue[::-1] 
     210        else: 
     211            # normal copy 
     212            cqueue = self.queue[:] 
     213 
     214        for pending in cqueue: 
     215            if event != pending[0]: 
     216                continue 
     217 
     218            self.queue.remove(pending) 
     219 
     220            # skip if requested 
     221            if not process: 
     222                continue 
     223 
     224            # alter state if only last one should be processed 
     225            if process == "last": 
     226                process = None 
     227 
     228            self.trigger(pending[0], *pending[1]) 
     229 
    96230EventManager = Events() 
    97231 
    98232if __name__ == "__main__": 
    99     def x(*c): 
    100         print "x", c 
    101  
    102     EventManager.subscribe(["test", "test2"], x) 
    103     EventManager.trigger("test", "one") 
    104     EventManager.trigger("test2", "two") 
    105     EventManager.unsubscribe(x, "test") 
    106 #    EventManager.unsubscribe(x) 
    107     EventManager.trigger("test", "one2") 
    108     EventManager.trigger("test2", "two2") 
     233    import doctest 
     234    doctest.testmod() 
  • SHX/trunk/src/SeismicHandler/core/modules/Trace.py

    r131 r137  
    2525""" 
    2626 
    27 from SeismicHandler.core import history, codes 
    2827from SeismicHandler.core.shlib import shlib 
    2928from SeismicHandler.core.log import logging 
     29from SeismicHandler.core.modules.Events import EventManager, Event 
     30from SeismicHandler.core.shheaders import MEMBLC 
    3031 
    3132from uuid import uuid4 as uuid 
     
    3738    """ 
    3839 
    39     def __init__(self): 
     40    def __init__(self, **kwargs): 
     41#        print kwargs["memblc"] 
     42        self.logger = logging.getLogger("modules.trace") 
     43         
    4044        # holds info entries 
    4145        self._info = {} 
     
    4448        self.id = uuid().hex 
    4549 
    46     def __getattr(self, attr): 
     50    def __getattr__(self, attr): 
    4751        """allow access to trace metadata by querying as attribute 
    4852 
     
    5357            return self.__dict__[attr] 
    5458 
     59    def plot(self): 
     60        self.logger.info("plot") 
     61 
     62    def delete(self): 
     63        self.logger.info("delete") 
     64 
     65    def update(self, **kwargs): 
     66        self.logger.info("update") 
     67 
    5568class Traces(object): 
     69    """ traces manipulation wrapper to shlib 
     70 
     71        - map sh memory traces to python structure 
     72    """ 
     73 
     74    # helds addresses and corresponding trace instances 
     75    traces = {} 
     76 
    5677    def __init__(self): 
    57         pass 
     78        self.sh = shlib().sh 
     79        EventManager.subscribe(Event(EventManager.REDRAW), self.update) 
     80        self.logger = logging.getLogger("modules.traces") 
     81        self.update() 
     82 
     83    def update(self, event=None): 
     84        # refresh root pointer 
     85        slib = self.sh 
     86        slib.db_root.restype = MEMBLC 
     87        root = slib.db_root() 
     88        self.logger.debug("%u traces available", root.im[0]) 
     89 
     90        # no traces left 
     91        if not root.im[0]: 
     92            # but still referenced here? 
     93            if len(self.traces): 
     94                # delete all 
     95                for t in self.traces: 
     96                    self.traces[t].delete() 
     97                self.trace = [] 
     98 
     99            return 
     100 
     101        addresses = [] 
     102        old_addresses = self.traces.keys() 
     103         
     104        p = root.pm[0] 
     105         
     106        while p: 
     107            addresses.append(p) 
     108             
     109            mb = MEMBLC.from_address(p) 
     110             
     111            if p in self.traces: 
     112                self.traces[p].update(memblc=mb) 
     113            else: 
     114                self.traces[p] = Trace(memblc=mb) 
     115             
     116            p = mb.pm[0] 
     117         
     118        new = list(set(addresses) - set(old_addresses)) 
     119        gone = list(set(old_addresses) - set(addresses)) 
     120         
     121        for addr in gone: 
     122            self.traces[addr].delete() 
     123 
     124        self.logger.debug("new traces: %s" % new) 
     125        self.logger.debug("gone traces: %s" % gone) 
     126            
     127if __name__ == "__main__": 
     128    t = Traces() 
     129    from SeismicHandler.core.commands import Run 
     130 
     131    EventManager.block(Event(EventManager.REDRAW)) 
     132    for i in range(2): 
     133        Run("cresharp") 
     134    EventManager.unblock(Event(EventManager.REDRAW)) 
     135    Run("del 1") 
  • SHX/trunk/src/SeismicHandler/core/modules/__init__.py

    r131 r137  
    1 # -*- coding: utf-8 -*- 
    2 # 
    3 # Copyright (C) 2008-2009 Marcus Walther (walther@szgrf.bgr.de) 
    4 # 
    5 # This file is part of Seismic Handler eXtended (SHX) 
    6 # Full details can be found at project website http://www.seismic-handler.org/ 
    7 #  
    8 # SHX is free software; you can redistribute it and/or modify 
    9 # it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by 
    10 # the Free Software Foundation; either version 3 of the License, or 
    11 # (at your option) any later version. 
    12 # 
    13 # SHX is distributed in the hope that it will be useful, 
    14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 
    15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    16 # GNU Lesser General Public License for more details. 
    17 # 
    18 # You should have received a copy of the GNU Lesser General Public License 
    19 # along with SHX (see license.txt); if not, write to the Free Software 
    20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
    21  
    22 """holds list of available internal modules""" 
    23  
    24 from SeismicHandler.core.log import logging 
    25 #from config.options import options, environment 
    26  
    27 class modulesClass(object): 
    28     """read available modules""" 
    29      
    30     modules = {} 
    31      
    32     def __new__(cls, *args, **kwargs): 
    33         """ensure single instance""" 
    34          
    35         if not '_the_instance' in cls.__dict__: 
    36             cls._the_instance = object.__new__(cls) 
    37              
    38         return cls._the_instance 
    39  
    40     def __init__(self): 
    41         if not self.modules: 
    42             self.update() 
    43              
    44     def update(self): 
    45         """update available modules on run-time""" 
    46          
    47         logger = logging.getLogger("core.modules") 
    48          
    49         modules = {} 
    50  
    51         import os 
    52         import fnmatch 
    53          
    54         for i in fnmatch.filter(os.listdir(__path__[0]), "[!_]*.py"): 
    55             # import module 
    56             imp = __import__(".".join((__name__,i[:-3])), locals(), globals(), [__name__]) 
    57             # get class (identical naming as module!) 
    58             modules[i[:-3]] = getattr(imp, i[:-3]) 
    59          
    60         logger.info("%u modules found" % len(modules)) 
    61         logger.debug(modules.keys()) 
    62          
    63         self.modules = modules 
    64  
    65 # shift modules into local namespace 
    66 for i in modulesClass().modules: 
    67     locals()[i] = modulesClass().modules[i] 
  • SHX/trunk/src/SeismicHandler/core/shlib.py

    r131 r137  
    3636from SeismicHandler.core.error import MultipleLibError, CommandStreamError, GotoTargetNotFoundError 
    3737from SeismicHandler.config.options import environment 
    38 from SeismicHandler.core.shheaders import LINELENGTH, NOERROR, PARAM, CAPCNV, MEMBLC 
     38from SeismicHandler.core.shheaders import LINELENGTH, NOERROR, PARAM, CAPCNV 
     39from SeismicHandler.core.modules.Events import EventManager, Event 
    3940 
    4041logger = logging.getLogger("core.shlib") 
     
    7071                logger.critical(("error loading shared lib", e)) 
    7172                sys.exit(1) 
    72  
    73             # import must be done here! 
    74             from SeismicHandler.core.modules.Events import EventManager 
    75             self.EventManager = EventManager 
    7673 
    7774            self._init() 
     
    164161            iscmdproc = C.c_int() 
    165162            rdlevel = C.c_int() 
    166             prompt = C.create_string_buffer(sys.ps1, LINELENGTH) 
     163             
     164            # check for prompt (not set if running non-interactively 
     165            try: 
     166                ptstr = sys.ps1 
     167            except AttributeError: 
     168                ptstr = "" 
     169                 
     170            prompt = C.create_string_buffer(ptstr, LINELENGTH) 
    167171 
    168172            # save tc, cc channel 
     
    183187 
    184188                if redraw.value: 
    185                     self.EventManager.trigger(self.EventManager.REDRAW) 
     189                    EventManager.trigger(Event(EventManager.REDRAW)) 
    186190 
    187191#                print quit.value, redraw.value, iscmdproc.value, rdlevel.value, status.value 
  • SHX/trunk/src/SeismicHandler/startup.py

    r131 r137  
    3535# finally import modules and commands for instant usage 
    3636from SeismicHandler.core.log import logging 
    37 from SeismicHandler.core.commands import * 
     37from SeismicHandler.core.commands import Run, Quit 
     38 
     39# just init adopted cmd line interface 
     40import SeismicHandler.config.init_shell 
    3841 
    3942# check for parameters (e.g. for scripts to run) 
Note: See TracChangeset for help on using the changeset viewer.