예제 #1
0
파일: reduction.py 프로젝트: twang817/glom
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
예제 #2
0
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``.
예제 #3
0
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
예제 #4
0
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
예제 #5
0
파일: matching.py 프로젝트: hydrogeohc/glom
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']
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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)
예제 #10
0
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
예제 #11
0
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)
예제 #12
0
    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)
예제 #13
0
파일: funcutils.py 프로젝트: blebo/boltons
    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):
예제 #14
0
    # 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
예제 #15
0
파일: grouping.py 프로젝트: ypankovych/glom
"""
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.
"""
예제 #16
0
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
예제 #17
0
    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):
예제 #18
0
def test_sentinel_falsiness():
    not_set = make_sentinel('not_set')
    assert not not_set
예제 #19
0
        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