Exemple #1
0
    def determine_bitmask(self):
        """
        Work out our bitmask value.

        if it's a callable and not an Enum class we call it with our packet to determine the bitmask.

        The bitmask must then be a subclass of enum.Enum

        And the bitmask must not have a member with the value zero
        """
        bitmask = self.bitmask
        if type(bitmask) is not enum.EnumMeta and callable(self.bitmask):
            bitmask = bitmask(self.pkt)

        try:
            if not issubclass(bitmask, enum.Enum):
                raise ProgrammerError("Bitmask is not an enum! got {0}".format(
                    repr(bitmask)))
        except TypeError:
            raise ProgrammerError("Bitmask is not an enum! got {0}".format(
                repr(bitmask)))

        for name, member in bitmask.__members__.items():
            if member.value == 0:
                raise ProgrammerError(
                    "A bitmask with a zero value item makes no sense: {0} in {1}"
                    .format(name, repr(bitmask)))

        return bitmask
Exemple #2
0
    def __init__(self, determine_res_packet, adjust_expected_number):
        if not callable(determine_res_packet) or not callable(
                adjust_expected_number):
            raise ProgrammerError("Multi Options expects two callables")

        self.determine_res_packet = determine_res_packet
        self.adjust_expected_number = adjust_expected_number
Exemple #3
0
def ChangeCleanCycle(*, enable, duration_s=0, duration=None, **kwargs):
    """
    Returns a valid message that will either start or stop the cleaning (HEV)
    cycle of devices used against it.

    When a cycle is started, if the duration_s=0 or is not provided, the default
    duration will be used.

    For example:

    .. code-block:: python

        await target.send(ChangeCleanCycle(enable=True), ["d073d5000001", "d073d5000001"])

    Options are:

        enable - boolean (required)
            Pass True to start a cleaning cycle or False to stop a cycle in progress

        duration_s - integer (optional)
            Only used if enable=True. Specifies the duration (in seconds) for
            the cleaning cycle. If not specified, the default duration will be
            used. Default duration can be set using target:set_clean_config and
            returned using target_get_clean_config
    """
    if duration is not None:
        raise ProgrammerError("Duration needs to be specified as duration_s")

    return ForCapability(hev=LightMessages.SetHevCycle(
        enable=enable,
        duration_s=duration_s,
        ack_required=True,
        res_required=False,
    ))
Exemple #4
0
def SetCleanConfig(*, indication, duration_s, duration=None, **kwargs):
    """
    Returns a valid message that will set the default clean cycle configuration
    for the device.

    For example:

    .. code-block:: python

        await target.send(SetCleanConfig(indication=True), ["d073d5000001", "d073d5000001"])

    The options are:

    indication - boolean - default False
        whether to run a short flashing indication at the end of the HEV cycle.

    duration_s - seconds - default 7200 seconds
        duration in seconds for a cleaning cycle, if no duration provided.
    """
    if duration is not None:
        raise ProgrammerError("Duration needs to be specified as duration_s")

    return ForCapability(hev=LightMessages.SetHevCycleConfiguration(
        indication=bool(indication),
        duration_s=duration_s,
        ack_required=True,
        res_required=False,
    ))
Exemple #5
0
    def until(self, major, minor, *conditions, becomes):
        if any((ma, mi) >= (major, minor) and conditions == conds
               for ma, mi, _, conds in self.upgrades):
            raise ProgrammerError(
                "Each .until must be for a greater version number")

        self.upgrades.append((major, minor, becomes, conditions))
        return self
Exemple #6
0
 def setup(self, pkt, enum, bitmask, unpacking=False, allow_float=False):
     self.pkt = pkt
     self.enum = enum
     self.bitmask = bitmask
     self.unpacking = unpacking
     self.allow_float = allow_float
     if self.enum and self.bitmask:
         raise ProgrammerError(
             "Sorry, can't specify enum and bitmask for the same type")
Exemple #7
0
    def setup(self):
        self.active = False
        self.packet_filter = Filter()

        self.final_future = None
        self.last_final_future = None

        if not hasattr(self, "io_source"):
            raise ProgrammerError(
                f"IO must have an io_source property: {self.__class__}")
Exemple #8
0
    def __getitem__(self, name):
        """Return a registered target template, or complain if one is not available under this name"""
        if not isinstance(name, str):
            raise ProgrammerError(
                f"Targets are key'd by their name but using {name}")

        if name in (None, sb.NotSpecified) or name not in self.registered:
            raise TargetNotFound(wanted=name,
                                 available=sorted(self.registered))

        return self.registered[name]
Exemple #9
0
    def transform(self, pack_func, unpack_func):
        """Set a ``pack_func`` and ``unpack_func`` for transforming the value for use"""
        for f in (pack_func, unpack_func):
            if not callable(f):
                raise ProgrammerError(
                    "Sorry, transform can only be given two callables")

        res = self.S(self.size_bits)
        res._transform = pack_func
        res._unpack_transform = unpack_func
        return res
Exemple #10
0
    def determine_enum(self):
        """
        Work out our enum value.

        if it's a callable and not an Enum class we call it with our packet to determine the enum.

        The bitmask must then be a subclass of enum.Enum
        """
        em = self.enum
        if type(em) is not enum.EnumMeta and callable(em):
            em = em(self.pkt)

        try:
            if not issubclass(em, enum.Enum):
                raise ProgrammerError("Enum is not an enum! got {0}".format(
                    repr(em)))
        except TypeError:
            raise ProgrammerError("Enum is not an enum! got {0}".format(
                repr(em)))

        return em
Exemple #11
0
    def __new__(metaname, classname, baseclasses, attrs):
        groups = {}
        all_names = []
        all_fields = []
        field_types = []
        format_types = []
        name_to_group = {}

        fields = attrs.get("fields")
        if fields is None:
            for kls in baseclasses:
                if hasattr(kls, "Meta") and hasattr(kls.Meta,
                                                    "original_fields"):
                    fields = kls.Meta.original_fields

        if fields is None:
            msg = "PacketSpecMixin expects a fields attribute on the class or a PacketSpec parent"
            raise ProgrammerError("{0}\tcreating={1}".format(msg, classname))

        if type(fields) is dict:
            msg = "PacketSpecMixin expect fields to be a list of tuples, not a dictionary"
            raise ProgrammerError("{0}\tcreating={1}".format(msg, classname))

        for name, typ in fields:
            if isinstance(typ, str):
                typ = attrs[typ]

            if hasattr(typ, "Meta"):
                groups[name] = []
                for n, _ in typ.Meta.field_types:
                    groups[name].append(n)
                    name_to_group[n] = name
                all_fields.extend(typ.Meta.field_types)
                all_names.extend(groups[name])
            else:
                all_names.append(name)
                all_fields.append((name, typ))
            format_types.append(typ)
            field_types.append((name, typ))

        if len(set(all_names)) != len(all_names):
            raise ProgrammerError("Duplicated names!\t{0}".format(
                [name for name in all_names if all_names.count(name) > 1]))

        class MetaRepr(type):
            def __repr__(self):
                return "<type {0}.Meta>".format(classname)

        Meta = type.__new__(
            MetaRepr,
            "Meta",
            (),
            {
                "multi": None,
                "groups": groups,
                "all_names": all_names,
                "field_types": field_types,
                "format_types": format_types,
                "name_to_group": name_to_group,
                "all_field_types": all_fields,
                "original_fields": fields,
                "field_types_dict": dict(field_types),
                "all_field_types_dict": dict(all_fields),
            },
        )

        attrs["Meta"] = Meta

        def dflt(in_group):
            return Initial if in_group else sb.NotSpecified

        attrs["fields"] = [(name, partial(dflt, name in groups))
                           for name in (list(all_names) + list(groups.keys()))]

        kls = type.__new__(metaname, classname, baseclasses, attrs)

        already_attributes = []
        for field in all_names:
            if hasattr(kls, field):
                already_attributes.append(field)
        if already_attributes:
            raise ProgrammerError(
                "Can't override attributes with fields\talready_attributes={0}"
                .format(sorted(already_attributes)))

        return kls
Exemple #12
0
 def value(self, cap):
     raise ProgrammerError(
         "CapabilityRange should only ever be present during definition time"
     )
Exemple #13
0
    def __init__(self, value):
        if not isinstance(value, tuple) or len(value) != 2:
            raise ProgrammerError(
                "Values in a capability range must be a tuple of two values")

        super().__init__(value)
Exemple #14
0
 def __init__(self, event=sb.NotSpecified):
     if event is sb.NotSpecified:
         raise ProgrammerError("Please use event.raise_stop() instead")
     self.event = event
Exemple #15
0
 def __init__(self, sender):
     if isinstance(sender, Target):
         raise ProgrammerError(
             "The Gatherer no longer takes in target instances. Please pass in a target.session result instead"
         )
     self.sender = sender