Esempio n. 1
0
    def _get_sub(
            self,
            key: str,
            ensure_sub_existance: bool = True) -> Nullable[Dict[Any, Any]]:
        '''
        Gets the /specified/ sub-context dictionary.

        If `ensure_sub_existance`, make sure it exists before returning it
        (create it with our bare entry if needed).

        Can return Null.
        '''
        full_ctx = None
        sub_ctx = None
        if ensure_sub_existance:
            sub_ctx = self._ensure(key)
            full_ctx = self._get(False)
        else:
            full_ctx = self._get(False)
            if not full_ctx:
                return Null()

        key = key or self._key
        sub_ctx = self.data.get(key, Null())
        return sub_ctx
Esempio n. 2
0
    def config(klass:          Type['config'],
               caller_name:    str,
               caller_dotted:  label.DotStr,
               caller_context: Optional['VerediContext'],
               raises_error:   Optional[bool] = True,
               ) -> Nullable['Configuration']:
        '''
        Checks for a CONFIG link in config's spot in this context. Returns it
        if it exists.

        If it doesn't exist use `raises_error` to either:
          - Throw an error via this class's `exception()`.
          - Just return Null().
        '''
        # Get it.
        ctx = klass._get()
        cfg_obj = ctx.get(Link.CONFIG, Null())

        # Error on it or return it?
        if not cfg_obj:
            if raises_error:
                msg = ("No Configuration present in the background "
                       "context; cannot get config setting for {} ({}) "
                       "without it.")
                raise klass.exception(
                    caller_context,
                    msg,
                    caller_name, caller_dotted)
            else:
                # Esure it's null as opposed to Null, None, or Falsy.
                cfg_obj = Null()
        return cfg_obj
Esempio n. 3
0
    def per_test_set_up(self):
        self.start_engine_and_events()
        entity = self.create_entity()

        # import veredi.zest.debug.background
        # veredi.zest.debug.background.to_log('zest_input_to_output')

        # Make our request event.
        request = self.data_request(entity.id, PF2Rank.Phylum.MONSTER,
                                    'Dragon', 'Aluminum Dragon')

        # print("per_test_set_up")
        # from veredi.zest.debug import background
        # background.to_log("unit-testing")

        # Trigger load with our request event.
        # Ask for our aluminum_dragon to be loaded. Expect 1 event for
        # each component in its data file.
        expected_events = len(self.expected_components)
        with log.LoggingManager.on_or_off(self.debugging):
            self.trigger_events(request, expected_events=expected_events)
        self.assertTrue(self.events)
        self.assertEqual(len(self.events), expected_events)

        # And we have DataLoadedEvents! Check 'em all; save the health one
        # for more checks.
        loaded_types = set()
        for loaded_event in self.events:
            self.assertIsInstance(loaded_event, DataLoadedEvent)

            # Did it make a thing?
            self.assertNotEqual(loaded_event.component_id, ComponentId.INVALID)

            # Get the thing and check it.
            component = self.manager.component.get(loaded_event.component_id)
            self.assertIsNotNone(component)
            self.assertEqual(loaded_event.component_id, component.id)
            self.assertIsInstance(component, DataComponent)
            comp_type = type(component)
            loaded_types.add(comp_type)

            # Make sure component and entity are enabled...
            self.force_alive(entity, component)

            # Not on entity because we don't have anyone hanging on them where
            # they belong yet...
            self.assertIs(entity.get(comp_type), Null())

            # Now stuff it in there.
            self.manager.entity.attach(entity.id, component)
            ent_comp = entity.get(comp_type)
            self.assertIsNot(ent_comp, Null())
            self.assertIs(ent_comp, component)

        # Now we have a set of all types - check against our expectations.
        self.assertEqual(loaded_types, self.expected_components)

        self.clear_events()
        return entity
Esempio n. 4
0
 def _get(klass: Type['registry'], key: str) -> Nullable[ContextMutableMap]:
     '''
     Get registry's full sub-context from background context.
     '''
     global _REGISTRY
     registry_entry = veredi.get().get(_REGISTRY, Null())
     sub_entry = registry_entry.get(key, Null())
     return sub_entry
Esempio n. 5
0
 def _get(klass: Type['ConfigRegistration'], path: 'ConfigRegistration',
          entry: Dict[str, Any]) -> Union[str, re.Pattern]:
     '''
     Get value at end of `path` keys in `entry`.
     '''
     if not path or not path.value:
         return Null()
     for node in path.value:
         entry = entry.get(node, Null())
     return entry
Esempio n. 6
0
    def _define_vars(self) -> None:
        '''
        Instance variable definitions, type hinting, doc strings, etc.
        '''

        # Initialize our fields with Null...
        self._record_storage: threads.Local = threads.Local(context=Null(),
                                                            group=Null(),
                                                            success=Null(),
                                                            exception=Null(),
                                                            stack=Null())
        '''
Esempio n. 7
0
    def exception(self,
                  clear:     Optional[bool]        = False,
                  exception: NullNoneOr[Exception] = None,
                  stack:     Optional[str]         = None) -> None:
        '''
        Save exception data off for injecting into LogRecord on filtering.

        If `clear` is True, saves `Null()` instead.
        '''
        if clear:
            self._record_storage.exception = Null()
            self._record_storage.stack = Null()
        else:
            self._record_storage.exception = exception
            self._record_storage.stack = stack
Esempio n. 8
0
 def testing(klass: Type['ConfigContext'],
             context: VerediContext) -> Nullable[bool]:
     '''
     Returns the unit-testing link field or Null.
     '''
     unit_testing = context._sub_get(klass.KEY, ConfigLink.UNIT_TESTING)
     return unit_testing or Null()
Esempio n. 9
0
 def subproc(klass: Type['ConfigContext'],
             context: VerediContext) -> Nullable['SubToProcComm']:
     '''
     Returns a SubToProcComm or Null.
     '''
     comms = context._sub_get(klass.KEY, ConfigLink.SUB_PROC)
     return comms or Null()
Esempio n. 10
0
    def _define_vars(self) -> None:
        '''
        Instance variable definitions, type hinting, doc strings, etc.
        '''
        super()._define_vars()

        self._seconds_per_round: Decimal = None
        '''
        How long in seconds that a round takes.

        It is definition data.
        '''

        self._current_round: int = -1
        '''
        The number of the current round. Multiply by `self._seconds_per_round`
        to get `self._current_seconds`.

        It is saved data.
        '''

        self._turn_order: Nullable[List[EntityId]] = Null()
        '''
        The current round's turn order for entities.
        '''

        self._turn_index: int = 0
        '''
Esempio n. 11
0
    def set_turn_order(self,
                       turn_order: NullNoneOr[Iterable[EntityId]],
                       preserve_turn: bool = True) -> None:
        '''
        Setter for the turn order list.

        If `preserve_turn` is True, this will try to keep the current turn on
        whatever entity it was on before the set.
          - This can fail and raise a ValueError if entity no longer exists in
            the list.

        If `preserve_turn` is False, this resets the turn order so that it is
        now the turn of the first entity in the new list.
        '''
        # First, if we're in a turn_order, and being set to a new one (as
        # opposed to it being deleted): check to see if we can/should
        # `preserve_turn`.
        new_index = 0
        if preserve_turn and self._turn_order and turn_order:
            curr_ent = self.turn
            if (curr_ent != EntityId.INVALID and curr_ent in turn_order):
                # Save their spot in the new list.
                new_index = turn_order.index(curr_ent)

        self._turn_order = turn_order or Null()
        self._turn_index = new_index
Esempio n. 12
0
    def get(self, *path: label.LabelInput) -> Nullable[Any]:
        '''
        Regularizes `path` to a dotted list:

        Returns value in main document under (converted) `path`.
          - Returns Null() if `path` does not exist.
        '''
        path = label.regularize(path)

        # Find out if there's anything at the end of the path.
        place = self._main()
        for key in path:
            # Check so we don't raise KeyError.
            if key not in place:
                return Null()

            # Update our place in the path and continue on to the next key.
            place = place[key]

        # We got here, so the path is either only a partial path, or we found a
        # leaf. We don't check for the difference right now, only return what
        # we ended up with.
        #
        # TODO: Figure out a way to return Null() if we're only a partial path?
        #   - Does DataDict have recursive DataDicts for sub-entries or
        #     something?
        return place
Esempio n. 13
0
    def test_command_execution(self):
        self.full_cmd_setup()

        cmd_str = 'unit-test 2 + 3'

        # Now ask for this to be executed. Should be a clean/valid input,
        # should have command name, should not have command prefix.
        status = self.commander.execute(
            None, cmd_str, self.user_input_ctx(cmd_str, Null(), None))

        # In normal usage, we may need EventManager to publish() once or thrice
        # (or not), depending on the command. Here we're unit testing so we
        # don't care about all that and our command is done now.
        #
        # It rudely did everything during execution/invocation instead of
        # holding back any heavy-weight lifting for its turn in the update
        # tick... probably. I may have walked back this assumption since then.
        # These are unit tests and tend to get ignored until they fail...
        #
        # So, hi. Sorry this is failing for you. :(
        self.assertTrue(self.cmd_was_triggered)

        # We get status back immediately. Should be a success.
        self.assertIsInstance(status, CommandStatus)
        self.assertTrue(status.success)
        self.assertEqual(status.command_safe, cmd_str)
Esempio n. 14
0
 def parsers(klass: Type['input']) -> Nullable['Parcel']:
     '''
     Checks for a CONFIG link in config's spot in this context.
     '''
     ctx = klass._get()
     retval = ctx.get(Link.PARSERS, Null())
     return retval
Esempio n. 15
0
 def _ability(self, name: str) -> Dict[str, Any]:
     '''
     Get `name`'s entry in our persistent data or null.
     '''
     entry = self.persistent.get(name, Null())
     log.debug("ABILITY: {} entry for {}: {}", self.klass, name, entry)
     return entry
Esempio n. 16
0
    def _sub_get(
        self,
        ctx_key: str,
        field: Union[str, enum.Enum],
        default: NullNoneOr[Any] = Null()
    ) -> Nullable[Any]:
        '''
        Gets `ctx_key` sub-context, then gets and returns value of `field`.

        Returns Null if ctx_key or field does not exist in this context, unless
        a `default` is provided.
        '''
        default = default or Null()
        full_ctx = self._get(False)
        sub_ctx = full_ctx.get(ctx_key, Null())
        return sub_ctx.get(field, Null()) or default
Esempio n. 17
0
    def get(self,
            id_or_type: CompIdOrType,
            allow_disabled: bool = False) -> Nullable[Component]:
        '''
        Gets a component from this entity by ComponentId or ComponentType. Will
        return the component instance or Null().
        '''
        # Try to get by type first...
        component = self._components.get(id_or_type, None)
        log.debug("Get component '{}' by type: {}", id_or_type, component)
        if component:
            return self.comp_or_null(component, allow_disabled)

        # Ok... id maybe?
        component = self._component_manager.get(id_or_type)
        if component:
            # Make sure it's ours...
            # TODO [2020-06-19]: compare by entity_id instead of getting again
            # and comparing instance id?
            my_comp = self._components.get(type(component), None)
            if my_comp and component == my_comp:
                # If we don't want disabled, and this one isn't enabled
                # (and is therefore disabled), there isn't one for you to
                # have.
                return self.comp_or_null(component, allow_disabled)

        # Fall thorough - ain't got that one.
        return Null()
Esempio n. 18
0
    def _update_mitosis(self) -> VerediHealth:
        '''
        Generic tick function. We do the same thing every tick state we process
        so do it all here.
        '''
        # Already did our broadcast - nothing more to do.
        if self._registration_broadcast:
            log.debug("CommandRegistrationBroadcast: Did our thing already.")
            return self._health_check(SystemTick.MITOSIS)

        # Doctor checkup.
        if not self._healthy(SystemTick.MITOSIS):
            self._health_meter_update = self._health_log(
                self._health_meter_update,
                log.Level.WARNING,
                "HEALTH({}): Skipping ticks - our system health "
                "isn't good enough to process.",
                self.health)
            return self._health_check(SystemTick.MITOSIS)

        reg_broadcast = self._commander.registration(self.id,
                                                     Null())
        log.debug("CommandRegistrationBroadcast about to broadcast: {}",
                  reg_broadcast)
        # TODO [2020-06-27]: better place to register these?
        veredi.zest.debug.registration.register(reg_broadcast)

        # All we want to do is send out the command registration broadcast.
        # Then we want to not tick this again.
        self._event_notify(reg_broadcast)
        self._registration_broadcast = True

        # Did a thing this tick so say we're PENDING...
        return VerediHealth.PENDING
Esempio n. 19
0
 def path(klass: Type['config']) -> Nullable[pathlib.Path]:
     '''
     Checks for a PATH link in config's spot in this context.
     '''
     ctx = klass._get()
     retval = ctx.get(Link.PATH, Null())
     return retval
Esempio n. 20
0
 def meeting(klass: Type['manager']) -> Nullable['Meeting']:
     '''
     Returns the Meeting of managers. Meeting has helper functions and maybe
     you want to access several managers from it?
     '''
     ctx = klass._get()
     retval = ctx.get(Link.MEETING, Null())
     return retval
Esempio n. 21
0
    def _get(self, data_type: DataType, *keychain: str) -> Any:
        '''
        Gets a value from the definition or saved data, depending
        on `data_type`.

        Follows `keychain` in order to find the value. Example
            data_type: DataType.DEFINITION
            keychain:  'time', 'round'
            definition:
                --- !definition.game
                time:
                  tick: veredi.game.time.tick.round
                  round: 6 seconds
          -> 6 seconds
             - TODO: Type? Probably a timespan?
        '''
        # ---
        # Sanity
        # ---
        # TODO: Verify keychain is correct for our document. Use a less
        # temporary solution than what Config does.
        #   Config's "temporary" solution:
        #     hierarchy = Document.hierarchy(doc_type)
        #     if not hierarchy.valid(*keychain):
        #         raise self._log_exception(
        #             exceptions.ConfigError,
        #             "Invalid keychain '{}' for {} document type. See its "
        #             "Hierarchy class for proper layout.",
        #             keychain, doc_type)

        # ---
        # Get the relevant record.
        # ---
        # Raises error if no data.
        data = self._data(data_type)

        # ---
        # Get the value by following the keychain.
        # ---
        value = data
        for key in keychain:
            value = value.get(key, None)
            if value is None:
                self._log_debug(
                    "No data for key {key} in keychain {keychain} "
                    "in our {data_type} data. "
                    "'{key}' data: {}, "
                    "all '{data_type}' data: {}",
                    value,
                    data,
                    key=key,
                    keychain=keychain,
                    data_type=data_type)
                return Null()

        return value
Esempio n. 22
0
    def get(self,
            cmd_or_alias: str) -> Tuple[Nullable[Command], Nullable[str]]:
        '''
        Get the command for `cmd_or_alias` string.

        Checks alias first so it can translate to command name and then only
        check commands once.

        Returns a tuple of:
          - command or Null
          - alias replacement, if `cmd_or_alias` is an alias or Null if not.
        '''
        alias = self._aliases.get(cmd_or_alias, Null())
        if alias:
            name, _ = sanitize.command_split(alias)
        else:
            name = cmd_or_alias

        return self._commands.get(name, Null()), alias
Esempio n. 23
0
    def _define_vars(self):
        '''
        Instance variable definitions, type hinting, doc strings, etc.
        '''
        self._debug: NullFalseOr[DebugFlag] = Null()
        '''
        Debug flags for managers.
        '''

        self._time_manager: NullFalseOr[TimeManager] = Null()
        '''
        "Singleton" for TimeManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._event_manager: NullFalseOr[EventManager] = Null()
        '''
        "Singleton" for EventManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._component_manager: NullFalseOr[ComponentManager] = Null()
        '''
        "Singleton" for ComponentManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._entity_manager: NullFalseOr[EntityManager] = Null()
        '''
        "Singleton" for EntityManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._system_manager: NullFalseOr[SystemManager] = Null()
        '''
        "Singleton" for SystemManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._data_manager: NullFalseOr[DataManager] = Null()
        '''
        "Singleton" for DataManager.
          - `False` indicates it explicitly does not exist.
          - `Null` indates it should but does not exist.
        '''

        self._identity_manager: NullFalseOr[IdentityManager] = Null()
        '''
Esempio n. 24
0
    def get(self, component_id: ComponentId) -> CompOrNull:
        '''
        USES Null PATTERN!!!

        Get component from the component pool and return it. Component's
        LifeCycle is not checked so it might not be alive yet/anymore.

        Returns the Component object or the Null() singleton object.
        '''
        return self._component_by_id.get(component_id, Null())
Esempio n. 25
0
 def get(klass: Type['veredi']) -> Nullable[ContextMutableMap]:
     '''
     Get Veredi's root of the background context. Anything else in the
     background context is assumed to be other's (e.g. plugin's?).
     '''
     global _CONTEXT, _ROOT
     if _CONTEXT is None:
         from copy import deepcopy
         _CONTEXT = deepcopy(_CONTEXT_LAYOUT)
     return _CONTEXT.get(_ROOT, Null())
    def per_test_set_up(self):
        self.set_up_events()
        entity = self.create_entity()

        # Make our request event.
        request = self.data_request(entity.id, PF2Rank.Phylum.NPC, 'Townville',
                                    'Skill Guy')
        self.assertFalse(self.events)

        # Ask for our Skill Guy data to be loaded.
        self.trigger_events(request)
        self.assertTrue(self.events)
        self.assertEqual(len(self.events), 1)

        # And we have a DataLoadedEvent!
        loaded_event = self.events[0]
        self.assertIsInstance(loaded_event, DataLoadedEvent)

        # Did it make a thing?
        self.assertNotEqual(loaded_event.component_id, ComponentId.INVALID)

        # Get the thing and check it.
        component = self.manager.component.get(loaded_event.component_id)
        self.assertIsNot(component, Null())
        self.assertEqual(loaded_event.component_id, component.id)
        self.assertIsInstance(component, SkillComponent)

        # Make sure component and entity are enabled...
        self.force_alive(entity, component)

        # Not on entity because we don't have anyone hanging on them where they
        # belong yet...
        self.assertIs(entity.get(SkillComponent), Null())

        # Now stuff it in there.
        self.manager.entity.attach(entity.id, component)
        ent_comp = entity.get(SkillComponent)
        self.assertIsNot(ent_comp, Null())
        self.assertIs(ent_comp, component)

        self.clear_events()
        return entity
Esempio n. 27
0
    def __init__(self,
                 debug_flags: NullNoneOr[DebugFlag]) -> None:

        self._define_vars()
        self._debug = debug_flags or Null()

        # ---
        # Logger!
        # ---
        # Set up ASAP so that we have self._log_*() working... ASAP? Yeah.
        self._log_config(self.dotted)
Esempio n. 28
0
    def sub_get(
        self, field: Union[str, enum.Enum], default: NullNoneOr[Any] = Null()
    ) -> Nullable[Any]:
        '''
        Gets this context's sub-context, then gets and returns value
        of `field`.

        Returns Null if sub-context or field does not exist in this
        context, unless a `default` is provided.
        '''
        return self._sub_get(self._key, field, default)
Esempio n. 29
0
 def comp_or_null(self,
                  component: Component,
                  allow_disabled: bool = False) -> Nullable[Component]:
     '''
     Obeys or ignores `Component.enabled` based on `allow_disabled`.
     Returns component or None.
     '''
     if not component.enabled:
         # Only return disabled component if allowed to.
         return component if allow_disabled else Null()
     return component
Esempio n. 30
0
    def context(self,
                clear:    Optional[bool]              = False,
                context:  NullNoneOr['VerediContext'] = None) -> None:
        '''
        Save context off for injecting into LogRecord on filtering.

        If `clear` is True, saves `Null()` instead.
        '''
        if clear is True:
            context = Null()
        self._record_storage.context = context