def __init__(self, session): """Create an instance of this menu tied to a session.""" super().__init__() self.session = session self._entries = self._entries.copy() self._entry_order = [] # TODO: Find out why these next two prevent these from being # garbage collected. I know that bound methods create circular # references with the instances but Python should detect that and # free both objects. It's not. # self.add_entry = self._inst_add_entry # self.remove_entry = self._inst_remove_entry # For now this is a work-around: self._add_entry_wr = WeakMethod(self._inst_add_entry) self._remove_entry_wr = WeakMethod(self._inst_remove_entry) def _add_entry(key, description, callback=None): return self._add_entry_wr()(key, description, callback) def _remove_entry(key): self._remove_entry_wr()(key) self.add_entry = _add_entry self.remove_entry = _remove_entry # Perform any instance-specific finalization. self._init() self._update_order()
def _get_handlers(self, args, kwargs): """Implement handler matching on arguments for set_handlers and remove_handlers. """ for obj in args: if inspect.isroutine(obj): # Single magically named function name = obj.__name__ if name not in self.event_types: raise EventException('Unknown event "%s"' % name) if inspect.ismethod(obj): yield name, WeakMethod(obj, partial(self._remove_handler, name)) else: yield name, obj else: # Single instance with magically named methods for name in dir(obj): if name in self.event_types: meth = getattr(obj, name) yield name, WeakMethod(meth, partial(self._remove_handler, name)) for name, handler in kwargs.items(): # Function for handling given event (no magic) if name not in self.event_types: raise EventException('Unknown event "%s"' % name) if inspect.ismethod(handler): yield name, WeakMethod(handler, partial(self._remove_handler, name)) else: yield name, handler
def __init__(self): super().__init__() self._get_weak_wr = WeakMethod(self._inst_get_weak) self._get_weak = lambda k: self._get_weak_wr()(k) self._set_weak_wr = WeakMethod(self._inst_set_weak) self._set_weak = lambda k, o: self._set_weak_wr()(k, o) self._del_weak_wr = WeakMethod(self._inst_del_weak) self._del_weak = lambda k: self._del_weak_wr()(k) self._weak_refs = WeakValueDictionary()
def __init__(self, merge_fn, sleep_interval=5): super().__init__(None, daemon=True) self._kill = Event() self._interval = sleep_interval # Weak ref to avoid keeping the SoonerDB instance in memory due to circular references. self._ref_to_fn = WeakMethod(merge_fn)
def connect(self, f: Callable): if hasattr(f, "__self__") and hasattr(f, "__func__"): self._handlers.add(WeakMethod(f, self._cleanup)) elif isinstance(f, object): self._handlers.add(ref(f, self._cleanup)) else: self._handlers.add(f)
def __init__(self, meth, callback=None, fallback=None): """ Create a weak proxy to a bound method. "callback" is called with this proxy as an argument when the underlying WeakMethod object goes stale. "fallback" is then used as a delegate instead. """ if callback: self_wr = weakref.ref(self) def _cb(arg): # The self-weakref trick is needed to avoid creating a reference # cycle. callback(self) self.weak_method = WeakMethod(meth, callback=_cb) else: self.weak_method = WeakMethod(meth) self.fallback = fallback
def __init__(self, job): """ Widget containing job information and buttons to perform specific job actions. The job information is treated as static: only updated if job notifies it. However, in a running job, the stdout is shown dynamically. Args: job: """ self.job = job self.info_widgets_list = [ ] # (sub)widget containing the job information self.file_widgets_list = [ ] # (sub)widget containing the last lines of certain files self.metadata_widgets_list = [ ] # (sub)widget containing the job information from the metadata self.update_info() # read job info self.handler = WeakMethod(self.update_info) self.job.state_change_handlers.append( self.handler ) # add handler to update information when the job status changes self.widget = urwid.Padding(None, align='center') self.update() # add the job info to the widget BaseTimedWidgetWrap.__init__(self, self.widget)
def disconnect(self, f: Callable): if hasattr(f, "__self__") and hasattr(f, "__func__"): self._handlers.remove(WeakMethod(f)) elif isinstance(f, object): self._handlers.remove(ref(f)) else: self._handlers.remove(f)
def register_refresher(self, token: Token, func: Refresher): if token not in self.tokens: if self.allow_new_token_on_register: self.tokens.add(token) else: raise InvalidRefreshToken(f"Token `{token}` is not a registered token") self.refresher_pairs.append((token, WeakMethod(func)))
def __init__(self, on_rerender=None, initial_state={}): if on_rerender is None: raise CreateComponentException( "Component must be created with create_child method. This error might be because kwargs not passed to super in component init method." ) self._children = [] self._intervals = [] self._render_cache = RenderCache() self._get_on_rerender = WeakMethod(on_rerender) self.state = State( initial_state={ **self.default_state, **initial_state }, on_state_update=self._on_state_update, ) self._reconciliation_lock = threading.Lock() self._reconciliation_queued = False self.active_event = threading.Event() self.mounted = False self.rendered = False self.width = None self.height = None self.size = None # replace subclass render method to add custom behaviour self._original_render = self.render self.render = self._render
def set_image_added(self, image_added: Optional[_OnImageAdded]) -> None: t_image_added = type(image_added) if None is image_added: self._image_added_wr = None elif MethodType is t_image_added: self._image_added_wr = WeakMethod(image_added) # type: ignore else: raise Exception('type {} not supported, yet'.format(t_image_added))
def MakeReference( callback: CallbackType, onFinalize: Optional[Callable[[Reference[CallbackType]], Any]]) \ -> Reference[CallbackType]: if ismethod(callback): return WeakMethod(callback, onFinalize) else: return ref(callback, onFinalize)
def __init__(self, f, weak: bool, once: bool): self.weak = weak if weak: if inspect.ismethod(f): f = WeakMethod(f) else: f = ref(f) self.f = f self.once = once
def __init__(self, execution_manager): self._execution_manager = execution_manager self.total_jobs = len(self._execution_manager.get_jobs()) for id_ in self._execution_manager.get_jobs(): job = self._execution_manager.get(id_) job.state_change_handlers.append(WeakMethod(self.job_state_handler)) print('Finished vs. total: {}'.format(self.get_ratio()))
def set_is_image_addable( self, is_image_addable: Optional[_IsImageAddable]) -> None: t_is_image_addable = type(is_image_addable) if None is is_image_addable: self._is_image_addable_wr = None elif MethodType is t_is_image_addable: self._is_image_addable_wr = WeakMethod( is_image_addable) # type: ignore else: raise Exception( 'type {} not supported, yet'.format(t_is_image_addable))
def get_weakref(func): """Get a weak reference to bound or unbound `func`. If `func` is unbound (i.e. has no __self__ attr) get a weakref.ref, otherwise get a wrapper that simulates weakref.ref. """ if func is None: raise ValueError if not hasattr(func, '__self__'): return weakref.ref(func) return WeakMethod(func)
def emit(self, *args, **kwargs): """Call all the connected slots with the provided args and kwargs. No action if block is activated. """ if self._block: return def _get_sender(): """Try to get the bound, class or module method calling the emit.""" prev_frame = sys._getframe(2) func_name = prev_frame.f_code.co_name # Faster to try/catch than checking for 'self' try: return getattr(prev_frame.f_locals['self'], func_name) except KeyError: return getattr(inspect.getmodule(prev_frame), func_name) # Get the sender try: self._sender = WeakMethod(_get_sender()) # Account for when func_name is at '<module>' except AttributeError: self._sender = None # Handle unsupported module level methods for WeakMethod. # TODO: Support module level methods. except TypeError: self._sender = None for slot in self._slots: if not slot: continue elif isinstance(slot, partial): slot(*args, **kwargs) elif isinstance(slot, weakref.WeakKeyDictionary): # For class methods, get the class object and call the method # accordingly. for obj, method in slot.items(): method(obj, *args, **kwargs) elif isinstance(slot, weakref.ref): # If it's a weakref, call the ref to get the instance # and then call the function. Don't wrap in try/except # so we don't risk masking exceptions from the actual func call tested_slot = slot() if tested_slot is not None: tested_slot(*args, **kwargs) else: # Else call it in a standard way. Should be just lambdas at # this point slot(*args, **kwargs)
def _get_fun_or_weakref(fun, weak): """Return the callable or a weak reference. Handles both bound and unbound methods. """ if not weak: return fun if inspect.ismethod(fun): return WeakMethod(fun) else: return ref(fun)
class WeakCallable: def __init__(self, callable: T.Callable, callback: T.Optional[T.Callable] = None) -> None: self._ref: ReferenceType if isinstance(callable, MethodType): self._ref = WeakMethod(callable, callback) else: self._ref = ref(callable, callback) def __call__(self, *args: T.Any, **kwargs: T.Any) -> T.Any: callable = self._ref() if callable is not None: return callable(*args, **kwargs) @property def ref(self) -> T.Any: return self._ref() def __eq__(self, other: T.Any) -> bool: if isinstance(other, WeakCallable): return self._ref.__eq__(other._ref) elif isinstance(other, ref): return self._ref.__eq__(other) else: return self._ref().__eq__(other) def __ne__(self, other: T.Any) -> bool: if isinstance(other, WeakCallable): return self._ref.__ne__(other._ref) elif isinstance(other, ref): return self._ref.__ne__(other) else: return self._ref().__ne__(other) def __hash__(self) -> int: return hash(self._ref)
def _set_when_changed(self, value): with self._when_changed_lock: if value is None: if self._when_changed is not None: self._disable_event_detect() self._when_changed = None else: enabled = self._when_changed is not None # Have to take care, if value is either a closure or a bound # method, not to keep a strong reference to the containing # object if isinstance(value, MethodType): self._when_changed = WeakMethod(value) else: self._when_changed = ref(value) if not enabled: self._enable_event_detect()
def subscribe( self, event: str, callback: Union[Callable[..., Any], types.MethodType]) -> int: """ Subscribe a callback to an event :arg event: String name of an event to subscribe to :callback: The function to call when the event is published. This can be any python callable. Use :func:`functools.partial` to call the callback with any other arguments. .. note:: The callback is registered with the event each time this method is called. The callback is called each time it has been registered when the event is published. For example:: >>> import asyncio >>> import pubmarine >>> pubpen = pubmarine.PubPen(asyncio.get_event_loop) >>> def message(): ... print('message called') >>> pubpen.subscribe('test', message) >>> pubpen.subscribe('test', message) >>> pubpen.publish('test') message called message called If the caller wants the callback to only be called once, it is the caller's responsibility to only subscribe the callback once. """ if self._event_list and event not in self._event_list: raise EventNotFoundError( '{} is not a registered event'.format(event)) # Get an id for the subscription sub_id = next(self._next_id) self._subscriptions[sub_id] = event if isinstance(callback, types.MethodType): # Add a method self._event_handlers[event][sub_id] = WeakMethod(callback) else: # Add a function self._event_handlers[event][sub_id] = ref(callback) return sub_id
def __init__(self, **kwargs): if self.draw_shadow is None: self.draw_shadow = WeakMethod(self.__draw_shadow__) self.prev_shadow_group = None im = BytesIO() Image.new("RGBA", (4, 4), color=(0, 0, 0, 0)).save(im, format="png") im.seek(0) self._soft_shadow_texture = self.hard_shadow_texture = CoreImage( im, ext="png").texture Clock.schedule_once(self.shadow_preset, -1) self.on_shadow_group(self, self.shadow_group) self.bind( pos=self._update_shadow, size=self._update_shadow, radius=self._update_shadow, ) super().__init__(**kwargs)
def __init__(self, port: int = 0) -> None: """Initialize the service. Args: port: Port to listen on. By default or if set to 0, port is chosen by the OS. """ self.records: List[Dict[str, Any]] = [] """ Records generated by Python's numerous Logstash packages have at least the following keys in common: * @timestamp: str - Log timestamp in ISO-8601 format. * @version: str - Logstash format version (always 1) * message: str - Log message. * host: str - Host sending the message. * path: str - Path to the module writing the log. * tags: List[str] - ? * type: str - "Logstash" * level: str - An all upper-case name of the log level * logger_name: str - Logger name * stack_info: Optional[str] - Formatted stacktrace if one exists. More keys may be added by the specific software sending the logs. """ root = socket.socket() root.bind(("0.0.0.0", port)) self._root = root # Avoiding a cyclic reference. _background = WeakMethod( self._background_thread) # type: ignore # typeshed bug. self._thread = threading.Thread(target=lambda: _background()(), daemon=True) self._selector = selectors.DefaultSelector() # Sockets used for signalling shutdown self._rshutdown, self._wshutdown = socket.socketpair() self.port: int = self._root.getsockname()[1]
def watch(self, caller: Optional[object] = None, callback: Optional[Callable] = None): '''Observer-like function that updates the currently loaded DB data. All callbacks are called immediately upon addition.\n caller: the object owning the callback, used to keep track and remove watchers\n callback: an optional callback to call whenever the pulled data is updated, of the form:\n \tfunc( GameCollection ) → any\n Returns the most up-to-date DB data as a one-time look ''' #error out if callback and no caller or vice versa if caller and not callback or callback and not caller: raise ValueError('Both caller and callback must be defined for watching') #try to add callback if exists, throw error if non-callable given if callback and caller: if callable(callback): self.__watchers.append((ref(caller), WeakMethod(callback))) callback(self.__data) else: raise TypeError('Callback given is not callable') #give static copy return self.__data
def __init__(self, **kwargs): self.draw_shadow = WeakMethod(self.__draw_shadow__) super().__init__(**kwargs)
def __init__(self, **kwargs): self.bind( radius=self._update_shadow, ) self.draw_shadow = WeakMethod(self.__draw_shadow__) super().__init__(**kwargs)
def __init__(self, **kwargs): self._shadow = MDApp.get_running_app().theme_cls.round_shadow self.draw_shadow = WeakMethod(self.__draw_shadow__) self._fake_elevation = True self._update_shadow(self, self.elevation) super().__init__(**kwargs)
def _create_ref(self, fun: SignalHandlerT) -> SignalHandlerRefT: if hasattr(fun, '__func__') and hasattr(fun, '__self__'): return cast(SignalHandlerRefT, WeakMethod(cast(MethodType, fun))) else: return ref(fun)
def subscribe_event(self, event, callback): ref = WeakMethod(callback) self._callback_events[event].append(ref)
def on_move(self, evt_function): self._on_move_function = WeakMethod(evt_function)