Пример #1
0
def wrap(
    cls_or_instance: Union[EnumEncode, Type[EnumEncode]]
) -> Union['EnumWrap', Type['EnumWrap']]:
    '''
    Returns the EnumWrap class for this enum `klass`.

    Returns None if not found.
    '''
    # Get Class:
    klass, is_class = _to_class(cls_or_instance)

    # Do we know of this guy?
    wrap_type = _WRAPPED_ENUMS.get(klass, None)

    # Return what we were given: instance or class type
    if is_class:
        log.data_processing(
            label.normalize(_DOTTED, 'wrap'), "wrap:\n"
            "  --in--> {}\n"
            "  --type- {}\n"
            "  <-type- {}", cls_or_instance, wrap_type, wrap_type)
        return wrap_type

    wrap_instance = wrap_type(cls_or_instance)
    log.data_processing(
        label.normalize(_DOTTED, 'wrap'), "wrap:\n"
        "  -in--> {}\n"
        "  -type- {}\n"
        "  <-out- {}", cls_or_instance, wrap_type, wrap_instance)
    return wrap_instance
Пример #2
0
 def recv(self) -> Tuple[Any, VerediContext]:
     '''
     Pull a package & context from the IPC pipe.
     '''
     package, context = self.pipe.recv()
     log.data_processing(self.dotted, "{} '{}' recv from sub-proc: {}, {}",
                         self.klass, self.name, package, context)
     return (package, context)
Пример #3
0
 def send(self, package: Any, context: VerediContext) -> None:
     '''
     Push package & context into IPC pipe.
     Waits/blocks until it receives something.
     '''
     log.data_processing(self.dotted, "{} '{}' send to sub-proc: {}, {}",
                         self.klass, self.name, package, context)
     self.pipe.send((package, context))
Пример #4
0
 def _ut_recv(self) -> Tuple[Any, VerediContext]:
     '''
     Pull a package & context from the IPC unit-testing pipe.
     '''
     package, context = self.ut_pipe.recv()
     log.data_processing(
         self.dotted, "{} '{}' TESTING pipe recv from main proc: {}, {}",
         self.klass, self.name, package, context)
     return (package, context)
Пример #5
0
 def _ut_send(self, package: Any, context: VerediContext) -> None:
     '''
     Push package & context into IPC unit-testing pipe.
     Waits/blocks until it receives something.
     '''
     log.data_processing(self.dotted,
                         "{} '{}' TESTING pipe send to main proc: {}, {}",
                         self.klass, self.name, package, context)
     self.ut_pipe.send((package, context))
Пример #6
0
def unwrap(instance: Union['EnumWrap', 'Encodable']) -> EnumEncode:
    '''
    If `instance` is an EnumWrap, returns the enum instance/value that the
    EnumWrap `instance` contains. Else returns `instance`.
    '''
    if not isinstance(instance, EnumWrap):
        log.data_processing(label.normalize(_DOTTED, 'unwrap'), "unwrap:\n"
                            "  --ignore-> {}\n"
                            "  <-ignore-- {}", instance, instance)
        return instance

    log.data_processing(label.normalize(_DOTTED, 'unwrap'), "unwrap:\n"
                        "  -in--> {}\n"
                        "  <-out- {}", instance, instance.enum)
    return instance.enum
Пример #7
0
    def get_data(self, *keychain: label.LabelInput) -> Nullable[Any]:
        '''
        Get a configuration thingy from us given some keychain use to walk into
        our config data in 'data' entry.

        Returns data found at end keychain.
        Returns None if couldn't find a key in our config data.
        '''
        # Ensure the keychain is in good shape from whatever was passed in.
        keychain = label.regularize(*keychain)

        data = self.get('data', *keychain)

        log.data_processing(self.dotted,
                            'get_data: keychain: {} -> data: {}',
                            keychain,
                            data,
                            log_minimum=log.Level.DEBUG)

        return data
Пример #8
0
    def get_by_doc(self, doc_type: Document,
                   *keychain: label.LabelInput) -> Nullable[Any]:
        '''
        Get value of `keychain` from `doc_type`.

        Raises a ConfigError if invalid `doc_type` supplied.
        Returns Null() if `doc_type` doesn't exist or `keychain` isn't in it.
        '''
        # Ensure the keychain is in good shape from whatever was passed in.
        keychain = label.regularize(*keychain)

        log.data_processing(self.dotted,
                            'get_by_doc: Getting doc: {}, keychain: {}...',
                            doc_type,
                            keychain,
                            log_minimum=log.Level.DEBUG)

        hierarchy = Document.hierarchy(doc_type)
        if not hierarchy.valid(*keychain):
            log.data_processing(self.dotted,
                                "get_by_doc: invalid document hierarchy for "
                                "doc: {}, keychain: {}...",
                                doc_type,
                                keychain,
                                log_minimum=log.Level.DEBUG)
            raise log.exception(
                ConfigError,
                "Invalid keychain '{}' for {} document type. See its "
                "Hierarchy class for proper layout.", keychain, doc_type)

        # Get document type data first.
        doc_data = self._config.get(doc_type, None)
        data = doc_data
        if data is None:
            log.data_processing(self.dotted,
                                "get_by_doc: No document type '{}' in "
                                "our config data: {}",
                                doc_type,
                                self._config,
                                log_minimum=log.Level.DEBUG,
                                log_success=False)
            return Null()

        # Now hunt for the keychain they wanted...
        for key in keychain:
            data = data.get(key, None)
            if data is None:
                log.data_processing(self.dotted,
                                    "get_by_doc: No data for key '{}' in "
                                    "keychain {} in our config "
                                    "document data: {}",
                                    key,
                                    keychain,
                                    doc_data,
                                    log_minimum=log.Level.DEBUG,
                                    log_success=False)
                return Null()

        log.data_processing(self.dotted, "get_by_doc: Got data for {} in "
                            "keychain {}. Data: {}",
                            doc_type,
                            keychain,
                            data,
                            log_minimum=log.Level.DEBUG,
                            log_success=True)
        return data
Пример #9
0
    def claim(
        klass: Type['Encodable'], data: EncodedEither
    ) -> Tuple[bool, Optional[EncodedEither], Optional[str]]:
        '''
        For simple encodings, looks for a match to the `klass._get_decode_rx()`
        regex.
          - Returns `data` as our claim.

        For complex encodings, looks for `klass.type_field()` in data. It
        should be one of these:
          - a top level key, with our encodable data as the key's value.
            - Returns `data[klass.type_field()]` as our claim.
        or
          - a top level 'claim' key, with our encodable data as all of `data`.
            - Returns `data` as our claim.

        Returns a tuple of:
          - bool: Can claim.
            - True if this Encodable class thinks it can/should decode this.
            - False otherwise.
          - EncodedEither:
            - Our claim of the data.
          - Optional[str]: Reason.
            - If can claim, this is None.
            - If cannot claim, this is a string describing why not.
        '''
        # log.data_processing(
        #     klass.dotted,
        #     "{} checking for claim of data:\n"
        #     "  {}",
        #     klass.klass, data)

        # ---
        # Simple?
        # ---
        # Is it EncodedSimple type and intended for this class?
        if klass.encoded_as(data) == Encoding.SIMPLE:
            # log.data_processing(
            #     klass.dotted,
            #     "{} checking for Encoding.SIMPLE claim of data:\n"
            #     "  {}",
            #     klass.klass, data)

            # If it's a simple encode and we don't have a decode regex for
            # that, then... No; It can't be ours.
            decode_rx = klass._get_decode_rx()
            if not decode_rx:
                # log.data_processing(
                #     klass.dotted,
                #     "{} has no Encoding.SIMPLE decode regex; "
                #     "cannot claim data:\n"
                #     "  {}",
                #     klass.klass, data)
                reason = (f"{klass.klass} is (probably) encoded simply "
                          f"but has no {klass.klass}._get_decode_rx(): "
                          f"rx: {decode_rx}, data: {data}")
                return False, None, reason

            # Check if decode_rx likes the data.
            claimed = bool(decode_rx.match(data))
            data_claim = data if claimed else None
            reason = (None if claimed else "No regex match.")
            if claimed:
                log.data_processing(
                    klass.dotted, "{} {} Encoding.SIMPLE data:\n"
                    "  {}", klass.klass,
                    'staking claim on' if claimed else 'will not claim', data)
            return claimed, data_claim, None

        # Does this class only do simple encode/decode?
        if not klass.encoding().has(Encoding.COMPLEX):
            # log.data_processing(
            #     klass.dotted,
            #     "{} was not Encoding.SIMPLE, and we don't do "
            #     "Encoding.COMPLEX. Will not claim data:\n"
            #     "  {}",
            #     klass.klass, data)

            return (False, None,
                    "Class only encodes simply and didn't match data.")

        # log.data_processing(
        #     klass.dotted,
        #     "{} checking for Encoding.COMPLEX claim of data:\n"
        #     "  {}",
        #     klass.klass, data)

        # ---
        # Complex?
        # ---
        # Else it's EncodedComplex.

        # Encoded with full registree information?
        if klass.was_encoded_with_registry(data):
            log.data_processing(
                klass.dotted,
                "{} was encoded with registry. Staking claim on data:\n"
                "  {}", klass.klass, data[klass.ENCODABLE_PAYLOAD_FIELD])
            return True, data[klass.ENCODABLE_PAYLOAD_FIELD], None

        # Are we a sub-field?
        if klass.type_field() in data:
            log.data_processing(
                klass.dotted,
                "{} was encoded with type_field. Staking claim on data:\n"
                "  {}", klass.klass, data[klass.type_field()])
            # Our type is a top level key, so our claim is the key's value.
            return True, data[klass.type_field()], None

        # Are we this whole thing?
        if klass._is_type_field(data):
            log.data_processing(
                klass.dotted,
                "{}... um... /is/ type_field? IDK. Staking claim on data:\n"
                "  {}", klass.klass, data)
            # Our type is in the 'type' field, so our claim is this whole
            # data thing.
            return True, data, None

        # ---
        # No Claim on Data.
        # ---
        # Doesn't have our type_field() value, so no.
        reason = (f"{klass.klass} is (probably) encoded but doesn't have "
                  f"our type-field ('{klass.type_field()}') at top level or "
                  "as 'type' value.")

        # # Debug output full data structure, but don't build the pretty string
        # # unless we're actually logging it.
        # if log.will_output(log.Group.DATA_PROCESSING):
        #     log.data_processing(
        #         klass.dotted,
        #         reason + "\n"
        #         + "Will not claim data:\n  {}",
        #         pretty.indented(data))

        return False, None, reason