class EventService(Service): def __init__(self, env): """event service""" super(EventService, self).__init__(env) self._channel = Signal('event_channel') def subscribe(self, func, event_type=None ): ''' :param func: def func(event_type, **kwarg): pass :param event_filter: option :return: ''' # sender = event_type or ANY # weak = True # if isinstance(event_type, basestring): # weak = False # self._channel.connect(func, sender, weak) sender = event_type or ANY self._channel.connect(func, sender) def unsubscribe(self, func): self._channel.disconnect(func) def publish(self, event_type, **kwarg): self._channel.send(event_type, **kwarg)
class CSession: def __init__(self, name, start, end): self.name = name self.uid = uuid.uuid1() self.start = datetime.strptime(start, DT_FORMAT) self.end = datetime.strptime(end, DT_FORMAT) self.on_live = Signal('on-live') self.on_end = Signal('on-end') self.liveURL = None self._teacher = None self.popups = [] @property def teacher(self): return self._teacher @teacher.setter def teacher(self, t): self.on_live.connect(t.live_recv) self.on_end.connect(t.session_end_recv) self._teacher = t def live(self): self.on_live.send(self, msg="hello") def liveEnd(self): self.on_end.send(self, msg="bye") def openLive(self): webbrowser.open_new(self.liveURL)
class WalkoffSignal(object): _signals = {} def __init__(self, name, event_type, loggable=True, message=''): self.name = name self.signal = Signal(name) self.event_type = event_type if loggable: signal_callback = partial(add_entry_to_case, data='', event_type=event_type.name, entry_message=message, message_name=name) self.connect(signal_callback, weak=False) def send(self, sender, **kwargs): self.signal.send(sender, **kwargs) def connect(self, func, weak=True): self.signal.connect(func) if not weak: WalkoffSignal._store_callback(func) return func @classmethod def _store_callback(cls, func): """ Stores callbacks so they aren't garbage collected and the weak references of the signals disappear """ cls._signals[id(func)] = func
class WalkoffSignal(object): """A signal to send Walkoff data The class is a wrapper around a blinker.Signal Attributes: name (str): The name of the signal signal (Signal): The signal object which sends the event and data event_type (EventType): The event type of this signal is_sent_to_interfaces (bool, optional): Should this event get sent to the interface dispatcher? Defaults to True message (str): Human readable message for this event Args: name (str): The name of the signal event_type (EventType): The event type of this signal send_to_interfaces (bool, optional): Should this event get sent to the interface dispatcher? Defaults to True message (str, optional): Human readable message for this event. Defaults to empty string """ _signals = {} def __init__(self, name, event_type, send_to_interfaces=True, message=''): self.name = name self.signal = Signal(name) self.event_type = event_type self.is_sent_to_interfaces = send_to_interfaces self.message = message def send(self, sender, **kwargs): """Sends the signal with data Args: sender: The thing that is sending the signal Kwargs: data: Additional data to send with the signal """ self.signal.send(sender, **kwargs) def connect(self, func, weak=True): """A decorator which registers a function as a callback for this signal Args: func (func): The function to register weak (bool, optional): Should a weak reference be used for this connection? Defaults to True Returns: func: The function connected """ self.signal.connect(func) if not weak: WalkoffSignal._store_callback(func) return func @classmethod def _store_callback(cls, func): """ Stores callbacks so they aren't garbage collected and the weak references of the signals disappear """ cls._signals[id(func)] = func
class WalkoffSignal(object): """A signal to send Walkoff data The class is a wrapper around a blinker.Signal Attributes: name (str): The name of the signal signal (Signal): The signal object which sends the event and data event_type (EventType): The event type of this signal is_sent_to_interfaces (bool, optional): Should this event get sent to the interface dispatcher? Defaults to True message (str): Human readable message for this event Args: name (str): The name of the signal event_type (EventType): The event type of this signal send_to_interfaces (bool, optional): Should this event get sent to the interface dispatcher? Defaults to True message (str, optional): Human readable message for this event. Defaults to empty string """ _signals = {} def __init__(self, name, event_type, send_to_interfaces=True, message=''): self.name = name self.signal = Signal(name) self.event_type = event_type self.is_sent_to_interfaces = send_to_interfaces self.message = message def send(self, sender, **kwargs): """Sends the signal with data Args: sender: The thing that is sending the signal Kwargs: data: Additional data to send with the signal """ self.signal.send(sender, **kwargs) def connect(self, func, weak=True): """A decorator which registers a function as a callback for this signal Args: func (func): The function to register weak (bool, optional): Should a weak reference be used for this connection? Defaults to True Returns: func: The function connected """ self.signal.connect(func) if not weak: WalkoffSignal._store_callback(func) return func @classmethod def _store_callback(cls, func): """ Stores callbacks so they aren't garbage collected and the weak references of the signals disappear """ cls._signals[id(func)] = func
class Event: def __init__(self, callback, name=''): self.signal = Signal() self.name = name self.callback = callback( name ) # needed b/c blinker cannot use weak references for callbacks self.signal.connect(self.callback) def send(self, sender): self.signal.send(sender)
class Foo: def __init__(self): self.on_hit = Signal() self.on_hit.connect(self.handle_hit) self.on_hit.connect(self.handle_again) def handle_hit(self, *args): print('hit!', self, args) def handle_again(self, *args): print('hit again!', self, args)
def anonymous_signal(): """ 匿名信号的例子 :return: no return """ # 定义一个信号 animal_signal = Signal() # 信号注册一个接收者 animal_signal.connect(animal) # 发送信号 animal_signal.send("anonymous")
class cons_d2c(object): '''包含约束的d2c类''' def __init__(self, d, constrains, init=True): ''' Parameters: d: 一个字典 constrains: 约束条目,每个元素都为一个三元元组(deps, func, target),例如, ( (('k1.k11','k1.k12'), (lambda v1,v2:v1+v2), 'k2' ), (('k3','k4'), (lambda v1,v2:(v1,v2)), ('k5','k6')), ) init: bool, 是否使用约束条件初始化传入的字典 ''' self.__d2c_instance = d2c(d) self.sig = Signal() self.constrains = constrains self.subscribers = self.__init_cons(constrains, init=init) def __init_cons(self, constrains, init=True): subscribers = [] for deps, func, target in constrains: subs = _subscrib(deps, func, target, self) subscribers.append(subs) for _k in deps: self.sig.connect(subs, sender=_k) if init: deps_set = set() for deps, func, target in constrains: deps_set.update(deps) for dep in deps_set: self.sig.send(dep) return subscribers def set(self, k, v, check=True): _changed = self.__d2c_instance.set(k, v, check=check) if _changed: self.sig.send(k) return _changed def get(self, k): return self.__d2c_instance.get(k) def update(self, d, check=True): k_changed = [] for k, v in d.items(): _changed = self.__d2c_instance.set(k, v, check=check) if _changed: k_changed.append(k) for _k in k_changed: self.sig.send(_k) def __getattr__(self, item): return getattr(self.__d2c_instance, item)
class Settings(): """Make multiple *Value instances accessible as a dict with their name as key""" def __init__(self, *values): # _values and _values_dict hold the same instances; the list is to # preserve order and the dict is for fast access via __getitem__ self._values = [] self._values_dict = {} self._on_change = Signal() self.load(*values) def add(self, value): """Add `value` to collection""" self._values.append(value) self._values_dict[value.name] = value def load(self, *values): """Add multiple `values` to collection""" for v in values: self.add(v) @property def values(self): """Iterate over collected values""" yield from self._values @property def names(self): """Iterate over values' `name` properties""" yield from self._values_dict.keys() def on_change(self, callback, autoremove=True): """ Run `callback` every time a value changes `callback` gets the value instances as the only argument. If `autoremove` is True, stop calling `callback` once it is garbage collected. """ self._on_change.connect(callback, weak=autoremove) def __getitem__(self, name): return self._values_dict[name] def __setitem__(self, name, value): self._values_dict[name].value = value self._on_change.send(self._values_dict[name]) def __contains__(self, name): return name in self._values_dict
def __construct_logging_signal(event_type, message_name, entry_message): """ Constructs a blinker Signal to log an event to the log database. Note: The returned callback must be stored to a module variable for the signal to work. :param event_type (str): Type of event whcih is logged 'Workflow, Step, etc.' :param message_name (str): Name of message :param entry_message (str): More detailed message to log :param data (str): Extra information :return: (signal, callback): The constructed blinker signal and its associated callback. """ signal = Signal(message_name) signal_callback = partial(__add_entry_to_case_wrapper, data='', event_type=event_type, message_name=message_name, entry_message=entry_message) signal.connect(signal_callback) return signal, signal_callback # need to return a tuple and save it to avoid weak reference
class Settings(): """Dict of ordered Value objects""" def __init__(self, *values): # _values and _values_dict hold the same instances; the list is to # preserve order and the dict is for access via __getitem__, etc. self._values = [] self._values_dict = {} self._on_change = Signal() self.load(*values) def add(self, value): self._values.append(value) self._values_dict[value.name] = value def load(self, *values): for v in values: self.add(v) @property def names(self): yield from self._values_dict.keys() @property def values(self): yield from self._values def on_change(self, callback, autoremove=True): """Run `callback` every time a value changes with the value If `autoremove` is True, stop calling callback once it is garbage collected. """ self._on_change.connect(callback, weak=autoremove) def __getitem__(self, name): return self._values_dict[name] def __setitem__(self, name, value): self._values_dict[name].set(value) self._on_change.send(self._values_dict[name]) def __contains__(self, name): return name in self._values_dict
def __construct_logging_signal(event_type, message_name, entry_message): """Constructs a blinker Signal to log an event to the log database. Note: The returned callback must be stored to a module variable for the signal to work. Args: event_type (str): Type of event which is logged 'Workflow, Action, etc.' message_name (str): Name of message entry_message (str): More detailed message to log Returns: (signal, callback): The constructed blinker signal and its associated callback. """ signal = Signal(message_name) signal_callback = partial(add_entry_to_case, data='', event_type=event_type, entry_message=entry_message, message_name=message_name) signal.connect(signal_callback) return signal, signal_callback # need to return a tuple and save it to avoid weak reference
class Settings(abc.Mapping): """Specialized mapping for *Value instances""" def __init__(self): self._defaults = {} self._values = {} self._constructors = {} self._descriptions = {} self._signals = {} self._global_signal = Signal() def add(self, name, constructor, default, description=None): """ Add new setting name: Identifier for this setting constructor: Callable that takes one argument and returns a new value for this setting default: Initial and default value description: What the setting does """ self._constructors[name] = constructor self._signals[name] = Signal() self._descriptions[name] = description self[name] = default self._defaults[name] = self[name] self._global_signal.send(self, name=name, value=self[name]) def reset(self, name): """Reset setting `name` to default/initial value""" self[name] = self._defaults[name] def default(self, name): """Return settings default/initial value""" return self._defaults[name] def description(self, name): """Return setting's description""" return self._descriptions[name] def syntax(self, name): """Return setting's description""" return self._constructors[name].syntax def validate(self, name, value): """Pass `value` to `name`'s constructor and return the result""" if not isinstance(value, str) and isinstance(value, abc.Iterable): return self._constructors[name](*value) else: return self._constructors[name](value) def on_change(self, callback, name=None, autoremove=True): """ Run `callback` every time a value changes If `name` is None, run `callback` if any signal changes. The signature of `callback` must be: (settings, name, value) If `autoremove` is True, stop calling `callback` once it is garbage collected. """ if name is None: self._global_signal.connect(callback, weak=autoremove) else: self._signals[name].connect(callback, weak=autoremove) def __getitem__(self, name): return self._values[name] def __setitem__(self, name, value): value_ = self.validate(name, value) self._values[name] = value_ self._global_signal.send(self, name=name, value=value_) self._signals[name].send(self, name=name, value=value_) def __contains__(self, name): return name in self._constructors def __iter__(self): return iter(self._constructors) def __len__(self): return len(self._constructors)
class ValueBase(): """Base class for *Value classes""" type = None # Something like int, str or tuple typename = 'anything' # User-readable explanation def __init__(self, name, *, default=None, description=None): self._name = str(name) self._description = str(description) or 'No description available' self._on_change = Signal() self._default = self._value = self._prev_value = None if default is not None: initial_value = self.convert(default) self.validate(initial_value) self._value = initial_value self._default = self._value log.debug('Initialized ValueBase: %s=%r', self._name, self._value) @property def name(self): return self._name @name.setter def name(self, name): self._name = str(name) @property def description(self): return self._description @description.setter def description(self, description): self._description = str(description) @property def value(self): """Convenience property for `get` method""" return self.get() @value.setter def value(self, value): self.set(value) @property def default(self): """Convenience property for `get_default` method""" return self.get_default() @default.setter def default(self, default): self.set_default(default) def get(self): """Return current value""" return self._value def set(self, value): """ Set current value When setting this property, callbacks connected to `on_change` get the current value (after validation). If one of the callbacks raises ValueError, the change is reverted and ValueError is raised. """ # convert() and validate() may raise ValueError new_value = self.convert(value) self.validate(new_value) # Set new value prev_value = self._value self._value = new_value # Callbacks can revert the change by raising ValueError try: self._on_change.send(self) except ValueError: self._value = prev_value raise else: self._prev_value = prev_value def get_default(self): """Return default value or `None` if no default is specified""" return self._default def set_default(self, default): """ Change default value Raise ValueError if `default` doesn't pass through `convert` and `validate` methods. """ try: new_default = self.convert(default) self.validate(new_default) except ValueError as e: raise ValueError('{} = {}: {}'.format(self.name, self.string(default), e)) else: self._default = new_default def prev_value(self): return self._prev_value def reset(self): """Reset current value back to default""" self.value = self.default def validate(self, value): """ Raise ValueError if `value` is not valid The default implementation checks if `value` is of the type specified in the class attribute `type`. If `type` is None (the default), all values valid. Additionally, subclasses may check for things like max/min length/number (see `StringValue` and `NumberValue` for examples). """ if self.type is not None and not isinstance(value, self.type): raise ValueError('Not a {}'.format(self.typename)) def convert(self, value, *args, **kwargs): """ Try to convert value to correct type before validation (e.g. str->int) Raise ValueError if impossible """ if self.type is None or isinstance(value, self.type): return value try: return self.type(value, *args, **kwargs) except Exception: raise ValueError('Not a {}'.format(self.typename)) def string(self, value=None, default=False): """ Return prettily stringified value value: The value to stringify or `None` to use `value` property default: Whether to stringify current or default value (setting this to True ignores the value argument) If possible, use `convert` to parse `value` before stringifying it. If `value` is invalid, `str(value)` or something similar should be returned so we can provide pretty error messages. This method must not raise any exceptions. """ if default: value = self.default elif value is not None: try: value = self.convert(value) except ValueError as e: value = value else: value = self.value # Display `None` as something more user-readable text = UNSPECIFIED if value is None else str(value) if not text or (text[0] == ' ' or text[-1] == ' '): return repr(text) else: return text def __str__(self): return self.string() def __repr__(self): v = self.value return '%s=%s' % (self.name, UNSPECIFIED if v is None else repr(v)) def __eq__(self, other): if isinstance(other, type(self)): return self.value == other.value else: return self.value == other def __ne__(self, other): return not self.__eq__(other) def __gt__(self, other): if isinstance(other, type(self)): return self.value > other.value try: return self.value > other except TypeError: return NotImplemented def __lt__(self, other): if isinstance(other, type(self)): return self.value < other.value try: return self.value < other except TypeError: return NotImplemented def __ge__(self, other): if isinstance(other, type(self)): return self.value >= other.value try: return self.value >= other except TypeError: return NotImplemented def __le__(self, other): if isinstance(other, type(self)): return self.value <= other.value try: return self.value <= other except TypeError: return NotImplemented def on_change(self, callback, autoremove=True): """ Pass this object to `callback` every time its value changes `callback` may raise ValueError to revert the change (see `set`). If `autoremove` is True, stop calling callback once it is garbage collected. """ self._on_change.connect(callback, weak=autoremove)
class BaseProcess(object): def __init__(self, new_func=None, total_count=None, *args, **kwargs): self.func = new_func self.total_count = total_count self.count = 0 self.task_queue = [] self.process_list = [] self.process_map = {} self.task_map = {} self.args = args self.kwargs = kwargs signal.signal(signal.SIGWINCH, self.action) # self.window = curses.initscr() self.add_task_signal = Signal(1000) self.count_signal = Signal(1001) self.reg_task_signal() self.reg_count_sinal() def reg_count_sinal(self): if not self.total_count: return else: self.count_signal.connect(self.process_count) def reg_task_signal(self): self.add_task_signal.connect(self.process_func) def create_new_task(self, work_num=1): for i in range(work_num): self.task_queue.append((self.func, self.args, self.kwargs)) self.add_task_signal.send() if self.total_count: for i in range(self.total_count): self.count_signal.send() self.process_map = {x: 0 for x in range(work_num)} def make_func(self): def add_count_deco(self, func): def wrapper(func): @functools.wraps(func) def _wrapper(*args, **kwargs): func(*args, **kwargs) self.count += 1 return _wrapper return wrapper @add_count_deco(self,self.func) def _make_func(*args,**kwargs): pass return _make_func def process_func(self, sender): while self.task_queue != []: self.task_queue.pop() process = multiprocessing.Process(target=self.func, args=self.args, kwargs=self.kwargs) process.start() def process_count(self, sender): self.count += 1 bar_length = 20 percent = float(self.count * 1.0 / self.total_count) hashes = '#' * int(percent * bar_length) spaces = ' ' * (bar_length - len(hashes)) multiprocessing.Process( target=sys.stdout.write("\rPercent: [%s] %d%%" % (hashes + spaces, percent * 100))).start() def action(self): key = self.window.getch() if key == ord('p'): pass if key == ord('r'): pass def start(self): while True: self.action()
class Settings(abc.Mapping): """Typed user configuration settings""" def __init__(self): self._defaults = {} self._values = {} self._constructors = {} self._getters = defaultdict(lambda: None) self._setters = defaultdict(lambda: None) self._descriptions = {} self._signals = defaultdict(lambda: Signal()) self._global_signal = Signal() def add(self, name, constructor, default, description=None, getter=None, setter=None): """ Add new setting name: Identifier for this setting constructor: Callable that takes one argument and returns a new value for this setting default: Initial and default value description: What the setting does getter: Callable with no arguments that returns the value setter: Callable with one argument that sets the value """ self._constructors[name] = constructor self._descriptions[name] = description value_ = self.validate(name, default) self._values[name] = value_ self._defaults[name] = value_ if getter: self._getters[name] = getter if setter: self._setters[name] = setter self._global_signal.send(self, name=name, value=value_) def reset(self, name): """Reset setting `name` to default/initial value""" self[name] = self._defaults[name] def default(self, name): """Return setting's default/initial value""" return self._defaults[name] def description(self, name): """Return setting's description""" return self._descriptions[name] def syntax(self, name): """Return setting's description""" return self._constructors[name].syntax def validate(self, name, value): """Pass `value` to `name`'s constructor and return the result""" if not isinstance(value, str) and isinstance(value, abc.Iterable): return self._constructors[name](*value) else: return self._constructors[name](value) def on_change(self, callback, name=None, autoremove=True): """ Run `callback` every time a value changes If `name` is None, run `callback` after every change. The signature of `callback` must be: (settings, name, value) If `autoremove` is True, stop calling `callback` once it is garbage collected. """ if name is None: self._global_signal.connect(callback, weak=autoremove) else: self._signals[name].connect(callback, weak=autoremove) @property def as_dict(self): # NOTE 1: The "id" key is important because filters (including # SettingFilter) expect it. This requirement can possibly # removed but it probably means rewriting lots of filter tests. # NOTE 2: The "validate" lambda MUST store the value of `name`, # otherwise `self.validate` always gets called with the for # loop's last `name` value. return {name:{'id': name, 'value': self[name], 'default': self.default(name), 'description': self.description(name), 'syntax': self.syntax(name), 'validate': lambda v, n=name: self.validate(n, v)} for name,value in self.items()} def __getitem__(self, name): getter = self._getters[name] if getter is not None: return self.validate(name, getter()) else: return self._values[name] def __setitem__(self, name, value): value_ = self.validate(name, value) setter = self._setters[name] if setter is not None: setter(value_) else: self._values[name] = value_ self._global_signal.send(self, name=name, value=value_) self._signals[name].send(self, name=name, value=value_) def __contains__(self, name): return name in self._constructors def __iter__(self): return iter(self._constructors) def __len__(self): return len(self._constructors)
class ValueBase(): """Name:value pair with validation, default value and description""" def __init__(self, name, default, description='No description available'): """Create new value""" self.__name = name self.__value = self.__default = self.convert(default) self.__description = description self.__on_change = Signal() # Must be set by derived classes type = NotImplemented typename = '<NOT IMPLEMENTED>' @property def value(self): return self.__value @property def name(self): return self.__name @property def default(self): return self.__default @property def description(self): return self.__description def on_change(self, callback, autoremove=True): """Pass this object to `callback` every time its value changes `callback` may raise ValueError to revert the change (see `set`). If `autoremove` is True, stop calling callback once it is garbage collected. """ self.__on_change.connect(callback, weak=autoremove) def set(self, value): """Change value if valid, reset to default if None Callbacks connected to `on_change` are passed this object every time a value is changed. If a callback raises ValueError, the change is reverted and a ValueError is raised. """ if value is None: value = self.__default try: new_value = self.convert(value) self.validate(new_value) except ValueError as e: raise ValueError('{} = {}: {}'.format(self.name, self.str(value), e)) else: prev_value = self.__value self.__value = new_value # Callbacks can revert the change by raising ValueError try: self.__on_change.send(self) except ValueError as e: self.__value = prev_value raise ValueError('{} = {}: {}'.format(self.name, self.str(value), e)) def get(self): """Return current value""" return self.value def validate(self, value): """Raise ValueError if value is not valid""" if not isinstance(value, self.type): raise ValueError('Not a {}'.format(self.typename)) def convert(self, value): """Try to convert value to correct type before validation (e.g. str->int) Raise ValueError if impossible""" if isinstance(value, self.type): return value try: if isinstance(value, abc.Iterable): return self.type(''.join(value)) else: return self.type(value) except Exception: raise ValueError('Not a {}'.format(self.typename)) def __eq__(self, other): return self.value == other.value def __ne__(self, other): return self.value != other.value def str(self, value=None, default=False): """Return prettily stringified value value: None to return current value, or specific value default: Whether to return current or default value """ if default: return str(self.default) elif value is not None: return str(value) else: return str(self.value) def __str__(self): return self.str() def __repr__(self): return '{}={!r}'.format(self.name, self.value)
class SignalEmitter: """Class that allows other callables to connect to it listen for signals. Callables can be attached to a SignalEmitter via SignalEmitter.connect. If the SignalEmitter calls SignalEmitter.signal.send(*args, **kwargs), any callables are called with the respective args and kwargs. Args: initialize_signal: instantiate a blnker.Signal object. If set to False, self.Signal needs to be set later on. This could be useful when you want a single Signal that is shared by all class instances. multiple_senders: Allow to be connected to multiple senders. If False, when connected to a second SignalEmitter, the connection to the previous SignalEmitter is disconnected Note: The SignalEmitter has protection against infinite recursions resulting from signal emitters calling each other. This is done by keeping track of the signal chain. However, it does not protect against infinite recursions from signals sent from objects that are not signal emitters. """ # Signal used for connecting to parameter via SignalEmitter.connect method signal = None def __init__(self, initialize_signal: bool = True, multiple_senders: bool = True): self._signal_chain = [] if initialize_signal: self.signal = Signal() self._signal_modifiers = {'offset': None, 'scale': None} # By default self is not connected to any other SignalEmitter self.sender = None self.multiple_senders = multiple_senders def connect(self, receiver, update=False, offset: float = None, scale: float = None): """Connect a receiver, which can be another SignalEmitter. If a SignalEmitter is passed, the __call__ method is invoked. Args: receiver: Receiver to be connected to this SignalEmitter's signal. offset: Optional offset to apply to emitted value scale: Optional scale to apply to emitted value Note: If offset or scale is provided, the emitted value should be a number. If an emitted signal contains 'value' as kwarg, this will be modified. Otherwise the first arg (sender) will be modified. """ if self.signal is None: self.signal = Signal() if isinstance(receiver, SignalEmitter): # Remove any previous sender if multiple_senders is False if not receiver.multiple_senders and receiver.sender is not None: receiver.sender.disconnect(receiver) receiver._signal_modifiers['offset'] = offset receiver._signal_modifiers['scale'] = scale self.signal.connect(receiver._signal_call) receiver.sender = self else: self.signal.connect(receiver) if update: # Update callable with current value value = self() if scale is not None: if callable(scale): scale = scale(self) value *= scale if offset is not None: if callable(offset): offset = offset(self) value += offset receiver(value) def disconnect(self, callable): """disconnect a callable from a SignalEmitter. Note: Does not raise error if callable is not connected in the first place """ if isinstance(callable, SignalEmitter): callable = callable._signal_call if getattr(self, 'signal', None) is not None: for receiver_ref in list(self.signal.receivers.values()): receiver = receiver_ref() if receiver == callable: self.signal.disconnect(callable) def _signal_call(self, sender, *args, **kwargs): """Method that is called instead of standard __call__ for SignalEmitters This method ensures that the actual __call__ is only invoked if this has not previously been done during the signal chain. """ if self not in self._signal_chain: value = kwargs.get('value', sender) # If any modifier is set, if self._signal_modifiers['scale'] is not None: scale = self._signal_modifiers['scale'] if callable(scale): scale = scale(self.sender) value *= scale if self._signal_modifiers['offset'] is not None: offset = self._signal_modifiers['offset'] if callable(offset): offset = offset(self.sender) value += offset if 'value' in kwargs: kwargs['value'] = value else: sender = value return self(sender, *args, signal_chain=self._signal_chain, **kwargs)
class TSys: gmaps = googlemaps.Client(key=GG_APIKEY) def __init__(self, name): self.name = name self.courses = [] self.cats = set() self.students = set() self.teachers = set() self.on_new_course = Signal('on-new-course') self.on_new_student = Signal('on-new-student') self.on_new_teacher = Signal('on-new-teacher') def commit(self): DbManager.commit(self.courses) DbManager.commit(self.teachers) DbManager.commit(self.students) return True def addCat(self, cat): for c in cat: self.cats.add(c) def direction(self, *args, **kwargs): return TSys.gmaps.directions(*args, **kwargs) def geocode(self, *args, **kwargs): return TSys.gmaps.geocode(*args, **kwargs) def _connectSignal(self, o): self.on_new_teacher.connect(o.newTeacherRecv) self.on_new_student.connect(o.newTeacherRecv) self.on_new_course.connect(o.newCourseRecv) def newTeacher(self, t): self.on_new_teacher.send(self, teacher=t) def newStudent(self, t): self.on_new_student.send(self, student=t) def newCourse(self, t): self.on_new_course.send(self, course=t) def addTeacher(self, t): self._connectSignal(t) found = [x for x in self.teachers if t.email == x.email] if len(found) == 0: self.teachers.add(t) self.newTeacher(t) return True else: return False def addStudent(self, s): self._connectSignal(s) found = [x for x in self.students if s.email == x.email] if len(found) == 0: self.students.add(s) self.newStudent(s) return True else: return False def studentLogin(self, email, passwd): found = [x for x in self.students if email == x.email] if len(found) > 0: if found[0].verify_password(passwd) == True: return found[0] else: return False else: return False def teacherLogin(self, email, passwd): found = [x for x in self.teachers if email == x.email] if len(found) > 0: if found[0].verify_password(passwd) == True: return found[0] else: return False else: return False def createCourse(self, course): self.courses.append(course) self.newCourse(course) def filter(self, cats): results = [] for c in cats: results.extend([x for x in self.courses if c in x.cats]) return results def find_students(self, filters): results = [] for s in self.students: match = True for k in filters.keys(): if k == "subject": match = filters[k] in s.subjects if k == "location": match = filters[k] in s.locations if k == "per_hour": if s.max_per_hour >= filters[k]: match = True else: match = False if match == False: break if match == True: results.append(s) return results