import operator import itertools from pprint import pprint from boltons.typeutils import make_sentinel from .core import TargetRegistry, Path, T, glom, GlomError, UnregisteredTarget _MISSING = make_sentinel('_MISSING') try: basestring except NameError: basestring = str class FoldError(GlomError): """Error raised when Fold() is called on non-iterable targets, and possibly other uses in the future.""" pass class Fold(object): """The `Fold` specifier type is glom's building block for reducing iterables in data, implementing the classic `fold <https://en.wikipedia.org/wiki/Fold_(higher-order_function)>`_ from functional programming, similar to Python's built-in :func:`reduce`. Args: subspec: A spec representing the target to fold, which must be
except ImportError: class RLock(object): # type: ignore """Dummy reentrant lock for builds without threads""" def __enter__(self): pass def __exit__(self, exctype, excinst, exctb): pass try: # noinspection PyUnresolvedReferences from boltons.typeutils import make_sentinel _MISSING = make_sentinel(var_name='_MISSING') _KWARG_MARK = make_sentinel(var_name='_KWARG_MARK') except ImportError: _MISSING = object() _KWARG_MARK = object() __all__ = ("LRI", "LRU") PREV, NEXT, KEY, VALUE = range(4) # names for the link fields DEFAULT_MAX_SIZE = 128 class LRI(dict): """The ``LRI`` implements the basic *Least Recently Inserted* strategy to caching. One could also think of this as a ``SizeLimitedDefaultDict``.
from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk import paramiko from smoke_zephyr.utilities import parse_server from smoke_zephyr.utilities import which if its.py_v2: from httplib import BadStatusLine else: from http.client import BadStatusLine USER_DATA_PATH = os.path.join(GLib.get_user_config_dir(), 'king-phisher') """The default folder location of user specific data storage.""" DISABLED = typeutils.make_sentinel('DISABLED') """A sentinel value to indicate that a feature is disabled.""" GTK3_DEFAULT_THEME = 'Adwaita' """The default GTK3 Theme for style information.""" if isinstance(Gtk.Widget, utilities.Mock): _Gtk_Application = type('Gtk.Application', (object, ), {'__module__': ''}) else: _Gtk_Application = Gtk.Application class KingPhisherClientApplication(_Gtk_Application): """ This is the top level King Phisher client object. It contains the custom GObject signals, keeps all the GUI references, and manages
from operator import attrgetter try: from threading import RLock except Exception: class RLock(object): 'Dummy reentrant lock for builds without threads' def __enter__(self): pass def __exit__(self, exctype, excinst, exctb): pass try: from boltons.typeutils import make_sentinel _MISSING = make_sentinel(var_name='_MISSING') _KWARG_MARK = make_sentinel(var_name='_KWARG_MARK') except ImportError: _MISSING = object() _KWARG_MARK = object() try: xrange except NameError: # py3 xrange = range unicode, str, bytes, basestring = str, bytes, bytes, (str, bytes) PREV, NEXT, KEY, VALUE = range(4) # names for the link fields DEFAULT_MAX_SIZE = 128
Sometimes you want to confirm that your target data matches your code's assumptions. With glom, you don't need a separate validation step, you can do these checks inline with your glom spec, using :class:`~glom.Match` and friends. """ import re import sys from pprint import pprint from boltons.iterutils import is_iterable from boltons.typeutils import make_sentinel from .core import GlomError, glom, T, MODE, bbrepr, bbformat, format_invocation, Path, chain_child, Val _MISSING = make_sentinel('_MISSING') # NOTE: it is important that MatchErrors be cheap to construct, # because negative matches are part of normal control flow # (e.g. often it is idiomatic to cascade from one possible match # to the next and take the first one that works) class MatchError(GlomError): """ Raised when a :class:`Match` or :data:`M` check fails. >>> glom({123: 'a'}, Match({'id': int})) Traceback (most recent call last): ... MatchError: key 123 didn't match any of ['id']
import getpass import keyword from boltons.strutils import pluralize, strip_ansi from boltons.iterutils import split, unique from boltons.typeutils import make_sentinel import face try: unicode except NameError: unicode = str raw_input = input ERROR = make_sentinel('ERROR') # used for parse_as=ERROR # keep it just to subset of valid ASCII python identifiers for now VALID_FLAG_RE = re.compile(r"^[A-z][-_A-z0-9]*\Z") FRIENDLY_TYPE_NAMES = {int: 'integer', float: 'decimal'} def process_command_name(name): """Validate and canonicalize a Command's name, generally on construction or at subcommand addition. Like ``flag_to_identifier()``, only letters, numbers, '-', and/or '_'. Must begin with a letter, and no trailing underscores or dashes. Python keywords are allowed, as subcommands are never used as
import re import sys import shlex import codecs import keyword import os.path from collections import OrderedDict from boltons.iterutils import split, unique from boltons.typeutils import make_sentinel from boltons.dictutils import OrderedMultiDict as OMD ERROR = make_sentinel('ERROR') class FaceException(Exception): """The basest base exception Face has. Rarely directly instantiated if ever, but useful for catching. """ pass class ArgumentParseError(FaceException): """A base exception used for all errors raised during argument parsing. Many subtypes have a ".from_parse()" classmethod that creates an exception message from the values available during the parse
import weakref import operator from abc import ABCMeta from pprint import pprint from collections import OrderedDict from boltons.typeutils import make_sentinel PY2 = (sys.version_info[0] == 2) if PY2: _AbstractIterableBase = object else: basestring = str _AbstractIterableBase = ABCMeta('_AbstractIterableBase', (object, ), {}) _MISSING = make_sentinel('_MISSING') OMIT = make_sentinel('OMIT') OMIT.__doc__ = """ The ``OMIT`` singleton can be returned from a function or included via a :class:`~glom.Literal` to cancel assignment into the output object. >>> target = {'a': 'b'} >>> spec = {'a': lambda t: t['a'] if t['a'] == 'a' else OMIT} >>> glom(target, spec) {} >>> target = {'a': 'a'} >>> glom(target, spec) {'a': 'a'} Mostly used to drop keys from dicts (as above) or filter objects from
class Checker(abc.ABC): """ Checker instances are used to validate some attribute of the state of an entity. Instances of this class are callables that take the arguments as shown on the `__call__` method. Implementing classes must override the `get_is_ok()` method. This method is used when you call an instance of this class. As such you can count on having access to the instance variables shown in the `__call__` method. This should be : self.es: the `AdvancedEntityState` which contains this checker self.actual_val: the actual value in the state self.expected_values: The values we're expecting. of course, this is set in the __init__ method, so if you override that, you may have something else. self.ha: An instance of the appdaemon HA class. Other useful methods that you may or may not want to override: get_fail_msg() / get_ok_msg() ============================= Gets the corresponding message to display/send/notify. """ NOT_CALLED = make_sentinel("NOT_CALLED", "NOT_CALLED") def __init__( self, *expected_values, fail_msg: str = None, ok_msg: str = None ) -> None: """ Set up checker with the values you're expecting to find. This is just an example implementation, you can of course override init with whatever logic and data you want. When instantiating the class you can provide functions that :param expected_values: A sequence of expected values. :param fail_msg: Provide your own "static" failure message. You can create more dynamic messages by overriding `get_fail_msg()`. :param ok_msg: Provide your own "static" ok message. You can create more dynamic messages by overriding `get_ok_msg()`. """ self.expected_values = expected_values self.static_fail_msg = fail_msg self.static_ok_msg = ok_msg self.es: Union[EntityState, Checker.NOT_CALLED] = Checker.NOT_CALLED self.actual_val: Union[Any, Checker.NOT_CALLED] = Checker.NOT_CALLED self.ha: Union[hass.Hass, Checker.NOT_CALLED] = Checker.NOT_CALLED @abc.abstractmethod def get_is_ok(self) -> bool: """ Whether our data passed the check or not. """ ... def _validate_called(self) -> None: """Helper method to make sure this instance has been called.""" assert all( ( self.es != Checker.NOT_CALLED, self.actual_val != Checker.NOT_CALLED, self.ha != Checker.NOT_CALLED, ) ), "Must call checker instance first." def get_fail_msg(self): self._validate_called() return ( getattr(self, "static_fail_msg", None) or f"{self.es.entity} failed check with a current value of `{self.actual_val}`." ) def get_ok_msg(self): self._validate_called() return ( getattr(self, "static_ok_msg", None) or f"{self.es.entity} passed check with a current value of `{self.actual_val}`." ) def get_msg(self, is_ok: bool) -> str: """ Get the failure or success message. :param is_ok: Whether our data passed the check. """ return self.get_ok_msg() if is_ok else self.get_fail_msg() def __call__(self, es: "EntityState", actual_val: str, ha: hass.Hass): self.es = es self.actual_val = actual_val self.ha = ha is_ok = self.get_is_ok() return is_ok, self.get_msg(is_ok)
from boltons.typeutils import make_sentinel NOMATCH = make_sentinel('NOMATCH', 'NOMATCH') def match1(*matches, name=None, default=NOMATCH): """ Pattern-matching for 1-argument functions match1( (lambda x: x > 5, 'high'), (lambda x: 2 < x <= 5, 'medium'), (lambda x: x <= 2, 'low'), )(3) """ def matching_function(x): for condition, action in matches: do_action = (callable(condition) and condition(x)) or x == condition if do_action: if callable(action): return action(x) else: return action else: if default is NOMATCH: raise ValueError('No match found') else: return default if name: matching_function.__name__ = name
class StateMonitor(hass.Hass): NOT_FOUND = make_sentinel("NOT_FOUND", "NOT_FOUND") # noinspection PyAttributeOutsideInit def initialize(self): self.current_failures: MutableMapping[int, datetime] = {} self.scheduled_re_checks: MutableMapping[int, int] = {} for es in ENTITY_STATES: assert es.is_setup, "EntityStates have not yet been initialized." self.log(f"Doing startup check and registering listener for {es.entity}.") # When appdaemon is initializing this app we check all states and alert # on them instead of waiting for a state change (which might be a long # time or never if the device is already in the failed state). self.do_entity_check(es) # ... and then we register a state listener self.listen_state(self.state_listener, es.entity, es=es) def state_listener(self, entity, attribute, old, new, kwargs): es: EntityState = kwargs.get("es", None) if not es: self.log("State listener fired without an attached EntityState", "ERROR") return self.do_entity_check(es) def do_entity_check(self, es: EntityState) -> None: """ Checks entity state. This is called by our registered state listener. However, this function does not actually do any actions or notifications. The reason for this is that to avoid spurious notifications and actions, this method actually schedule a re-check of the entity's state in a few seconds. This re-check is where notifications and actions are fired. """ self.log(f"Checking state of {es.entity_accessor}", "DEBUG") is_ok, msg = self.is_ok(es) if is_ok and self.is_currently_failed(es): # This is something that was not-ok but then came back into compliance. self.log( f"{es.entity_accessor} failed but came back. Removing from " f"current failures. (msg: {msg})." ) self.do_ok_notify(es, msg) # Don't need to track it anymore. self.pop_failed(es) # In case the entity goes compliant and then not compliant again before # the re-check happens we need to make sure there are no scheduled # re-checks any time an entity transitions to an OK state. self.unschedule_re_check(es) elif is_ok: # This entity is fine, no need to do anything! self.log(f"{es.entity_accessor} is fine.", "DEBUG") elif self.is_currently_failed(es): # The state of a currently failed entity has changed from one failed # state to another failed state, so update action/notification self.do_fail_notify(es, msg) else: # Entity just became non-compliant, so schedule a re-check of its state # in a few seconds. ("few seconds" means however many seconds is in # `es.fail_delay`.) self.log( f"{es.entity_accessor} in fail state. Scheduling recheck in " f"{es.fail_delay} seconds.", "INFO", ) self.schedule_re_check(es) def schedule_re_check(self, es: EntityState): self.scheduled_re_checks[es.id] = self.run_in( self.re_check, es.fail_delay, es=es ) def unschedule_re_check(self, es: EntityState): if es.id in self.scheduled_re_checks: self.cancel_timer(self.scheduled_re_checks.pop(es.id)) def is_ok(self, es: EntityState) -> Tuple[bool, str]: """ Checks if an entity is ok. Returns a tuple. First element is a bool where True means everything is fine, and False means OH NOES. Second element of the tuple is a message describing the state. """ value = get_nested_attr( self.entities, es.entity_accessor, default=StateMonitor.NOT_FOUND ) # Guard against mis-configuration of EntityStates or when entities have # disappeared from HA for some reason. if value == StateMonitor.NOT_FOUND: err = f"Cannot find `{es.entity_accessor}`" self.log(err, "ERROR") return False, err # The signature for `EntityState.is_ok_when` is the signature of the # `Checker.__call__` and `Checker`'s descendents. return es.is_ok_when(es, value, self) def re_check(self, kwargs) -> None: """Do actions/notifications on failed entity state. This simple method is the whole point of this class...notifications and actions on non-compliant entity states. See `do_entity_check` for more info. """ es = kwargs["es"] # Don't need to track the handle for the timer that fires this method any # longer...because that timer is how this method was run, so our handle to # the timer is invalid anyway. self.scheduled_re_checks.pop(es.id) is_ok, msg = self.is_ok(es) if is_ok: self.log(f"{es.entity_accessor} was temporarily in a fail state.", "DEBUG") else: self.add_failed(es) self.do_fail_notify(es, msg) def do_fail_notify(self, es: EntityState, msg): self.log(msg, "WARNING") self.call_service( "notify/main_html", title="Abnormal State", message=msg, data={"tag": es.id} ) def do_ok_notify(self, es: EntityState, msg): self.log(msg, "INFO") failed_time = datetime.now() - self.get_failed(es) self.call_service( "notify/main_html", title="Re-Enter Normal State", message=f"{msg} (Failed for: {failed_time})", data={"tag": es.id}, ) def add_failed(self, es: EntityState) -> None: if not self.is_currently_failed(es): self.current_failures[es.id] = datetime.now() def is_currently_failed(self, es: EntityState) -> bool: return es.id in self.current_failures def get_failed(self, es: EntityState) -> datetime: return self.current_failures[es.id] def pop_failed(self, es: EntityState) -> datetime: return self.current_failures.pop(es.id)
def add_failed(self, es: EntityState) -> None: if not self.is_currently_failed(es): self.current_failures[es.id] = datetime.now() def is_currently_failed(self, es: EntityState) -> bool: return es.id in self.current_failures def get_failed(self, es: EntityState) -> datetime: return self.current_failures[es.id] def pop_failed(self, es: EntityState) -> datetime: return self.current_failures.pop(es.id) DEFAULT = make_sentinel("DEFAULT", "DEFAULT") def get_nested_attr(obj, attribute: str, default=DEFAULT): """ Get a named attribute from an object. `get_nested_attr(x, 'a.b.c.d')` is equivalent to `x.a.b.c.d`. When a default argument is given, it is returned when any attribute in the chain doesn't exist; without it, an exception is raised when a missing attribute is encountered. """ getter = attrgetter(attribute) try: return getter(obj)
basestring = (str, bytes) # Python 3 compat _IS_PY2 = False else: _IS_PY2 = True try: _inspect_iscoroutinefunction = inspect.iscoroutinefunction except AttributeError: # Python 3.4 _inspect_iscoroutinefunction = lambda func: False try: from boltons.typeutils import make_sentinel NO_DEFAULT = make_sentinel(var_name='NO_DEFAULT') except ImportError: NO_DEFAULT = object() def get_module_callables(mod, ignore=None): """Returns two maps of (*types*, *funcs*) from *mod*, optionally ignoring based on the :class:`bool` return value of the *ignore* callable. *mod* can be a string name of a module in :data:`sys.modules` or the module instance itself. """ if isinstance(mod, basestring): mod = sys.modules[mod] types, funcs = {}, {} for attr_name in dir(mod): if ignore and ignore(attr_name):
# Python 3 make_method = lambda desc, obj, obj_type: MethodType(desc, obj) basestring = (str, bytes) # Python 3 compat _IS_PY2 = False else: _IS_PY2 = True try: _inspect_iscoroutinefunction = inspect.iscoroutinefunction except AttributeError: # Python 3.4 _inspect_iscoroutinefunction = lambda func: False try: from boltons.typeutils import make_sentinel NO_DEFAULT = make_sentinel(var_name='NO_DEFAULT') except ImportError: NO_DEFAULT = object() try: from functools import partialmethod except ImportError: partialmethod = None _IS_PY35 = sys.version_info >= (3, 5) if not _IS_PY35: # py35+ wants you to use signature instead, but # inspect_formatargspec is way simpler for what it is. Copied the # vendoring approach from alembic: # https://github.com/sqlalchemy/alembic/blob/4cdad6aec32b4b5573a2009cc356cb4b144bd359/alembic/util/compat.py#L92 from inspect import formatargspec as inspect_formatargspec
""" Group mode """ from __future__ import division import random from boltons.typeutils import make_sentinel from .core import glom, MODE, SKIP, STOP, TargetRegistry, Path, T, BadSpec, _MISSING ACC_TREE = make_sentinel('ACC_TREE') ACC_TREE.__doc__ = """ tree of accumulators for aggregation; structure roughly corresponds to the result, but is not 1:1; instead the main purpose is to ensure data is kept until the Group() finishes executing """ CUR_AGG = make_sentinel('CUR_AGG') CUR_AGG.__doc__ = """ the spec which is currently performing aggregation -- useful for specs that want to work in either "aggregate" mode, or "spec" mode depending on if they are in Group mode or not; this sentinel in the Scope allows a spec to decide if it is "closest" to the Group and so should behave like an aggregate, or if it is further away and so should have normal spec behavior. """
from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk import paramiko from smoke_zephyr.utilities import parse_server from smoke_zephyr.utilities import which if its.py_v2: from httplib import BadStatusLine else: from http.client import BadStatusLine USER_DATA_PATH = os.path.join(GLib.get_user_config_dir(), 'king-phisher') """The default folder location of user specific data storage.""" DISABLED = typeutils.make_sentinel('DISABLED') """A sentinel value to indicate that a feature is disabled.""" GTK3_DEFAULT_THEME = 'Adwaita' """The default GTK3 Theme for style information.""" if isinstance(Gtk.Widget, utilities.Mock): _Gtk_Application = type('Gtk.Application', (object,), {'__module__': ''}) else: _Gtk_Application = Gtk.Application class KingPhisherClientApplication(_Gtk_Application): """ This is the top level King Phisher client object. It contains the custom GObject signals, keeps all the GUI references, and manages the RPC client object. This is also the parent window for most
make_method = lambda desc, obj, obj_type: MethodType(desc, obj) # noqa basestring = (str, bytes) # Python 3 compat _IS_PY2 = False else: _IS_PY2 = True try: _inspect_iscoroutinefunction = inspect.iscoroutinefunction except AttributeError: # Python 3.4 _inspect_iscoroutinefunction = lambda func: False # noqa try: from boltons.typeutils import make_sentinel NO_DEFAULT = make_sentinel(var_name="NO_DEFAULT") except ImportError: NO_DEFAULT = object() def get_module_callables(mod, ignore=None): """Returns two maps of (*types*, *funcs*) from *mod*, optionally ignoring based on the :class:`bool` return value of the *ignore* callable. *mod* can be a string name of a module in :data:`sys.modules` or the module instance itself. """ if isinstance(mod, basestring): mod = sys.modules[mod] types, funcs = {}, {} for attr_name in dir(mod): if ignore and ignore(attr_name):
def test_sentinel_falsiness(): not_set = make_sentinel('not_set') assert not not_set
we skip the method. :return: Returns the decorator we want to use on a class. """ @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): if not (instance is None and inspect.isclass(wrapped)): raise TypeError("Use `method_decorator` on classes.") for name, fn in inspect.getmembers(wrapped, inspect.isfunction): if all(predicate(fn) for predicate in predicates): setattr(wrapped, name, decorator(fn)) return wrapped(*args, **kwargs) return wrapper dontcheck = make_sentinel("dontcheck", "dontcheck") def has_parameter(parameter_name: str, annotation: Optional[type] = dontcheck) -> PredicateCallable: """Creates a predicate that checks for an arg name in a function signature. :param parameter_name: The name of the parameter we want to check for. :param annotation: If provided, checks that the annotation matches this. """ def predicate(func: AnyCallable) -> bool: sig = inspect.signature(func) parameter = sig.parameters.get(parameter_name) if not parameter: return False