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()
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()
def log_level(klass: Type['ConfigContext'], context: VerediContext) -> log.Level: ''' Returns log_level in `context` or Null. ''' return log.Level.to_logging( context._sub_get(klass.KEY, ConfigLink.LOG_LEVEL))
def keychain(klass: Type['ConfigContext'], context: VerediContext) -> Nullable[Iterable[Any]]: ''' Checks for a KEYCHAIN link in config's spot in this context. ''' keychain = context.sub_get(ConfigLink.KEYCHAIN) return keychain
def source_id(klass: Type['InputContext'], context: VerediContext) -> Union[int, 'MonotonicId']: ''' If there is a source id (EntityId, whatever), get it. ''' input_ctx = context._get().get(klass.KEY, {}) ident = input_ctx.get(InputLink.SOURCE_ID, None) return ident
def source_designation(klass: Type['InputContext'], context: VerediContext) -> Optional[str]: ''' Checks for & returns our Input ID or InputId.INVALID. ''' input_ctx = context._get().get(klass.KEY, {}) designation = input_ctx.get(InputLink.SOURCE_DESIGNATION, None) return designation
def input_id(klass: Type['InputContext'], context: VerediContext) -> Optional[InputId]: ''' Checks for & returns our Input ID or InputId.INVALID. ''' input_ctx = context._get().get(klass.KEY, {}) input_id = input_ctx.get(InputLink.INPUT_ID, InputId.INVALID) return input_id
def log_is_server(klass: Type['ConfigContext'], context: VerediContext) -> bool: ''' Returns True if the process is a log_server. ''' # _sub_get() returns None if key not found, which is convenient for # converting to a bool. return bool(context._sub_get(klass.KEY, ConfigLink.LOG_SERVER))
def type(klass: Type['InputContext'], context: VerediContext) -> Union[int, enum.Enum]: ''' If there is a type id, get it. ''' input_ctx = context._get().get(klass.KEY, {}) type_id = input_ctx.get(InputLink.TYPE, None) return type_id
def input(klass: Type['InputContext'], context: VerediContext) -> Optional[str]: ''' Checks for & returns our input string or None. ''' input_ctx = context._get().get(klass.KEY, {}) input_id = input_ctx.get(InputLink.INPUT_SAFE, None) return input_id
def id(klass: Type['ConfigContext'], context: VerediContext) -> Nullable[Any]: ''' Checks for an ID link in config's spot in this context. If none, returns Null(). ''' id = context.sub_get(ConfigLink.ID) if not id: log.debug("No id in context! context.id: {}, ", id, context=context) return id
def path(klass: Type['ConfigContext'], context: VerediContext) -> Nullable[pathlib.Path]: ''' Checks for a PATH link in config's spot in this context. If none, returns PATH from background.manager.data. ''' path = context.sub_get(ConfigLink.PATH) if null_or_none(path): log.debug( "No path in context; using background's. " "context.path: {}, ", "bg.path: {}", path, background.manager.data.path, context=context) path = background.manager.data.path return path
def set_testing(klass: Type['ConfigContext'], context: VerediContext, value: 'SubToProcComm') -> None: ''' Sets the unit-testing link field. Pops if `value` is None. ''' context._sub_set(klass.KEY, ConfigLink.UNIT_TESTING, value)
def set_log_is_server(klass: Type['ConfigContext'], context: VerediContext, is_server: bool) -> None: ''' Set is_server in `context`. Pops if `is_server` is None. ''' context._sub_set(klass.KEY, ConfigLink.LOG_SERVER, is_server)
def set_log_level(klass: Type['ConfigContext'], context: VerediContext, level: log.LogLvlConversion) -> None: ''' Sets log_level in `context`. Pops if `level` is None. ''' context._sub_set(klass.KEY, ConfigLink.LOG_LEVEL, level)
def set_subproc(klass: Type['ConfigContext'], context: VerediContext, value: 'SubToProcComm') -> None: ''' Sets a SubToProcComm. Pops if `value` is None. ''' context._sub_set(klass.KEY, ConfigLink.SUB_PROC, value)
def set_up( proc_name: str, config: Configuration, context: VerediContext, entry_fn: StartProcFn, t_proc_to_sub: Type['ProcToSubComm'] = ProcToSubComm, t_sub_to_proc: Type['SubToProcComm'] = SubToProcComm, finalize_fn: FinalizeInitFn = None, initial_log_level: Optional[log.Level] = None, debug_flags: Optional[DebugFlag] = None, unit_testing: Optional[bool] = False, proc_test: Optional[ProcTest] = None, shutdown: Optional[multiprocessing.Event] = None ) -> Optional[ProcToSubComm]: ''' Get a process ready for _run_proc(). If `t_proc_to_sub` and/or `t_sub_to_proc` are not default, those classes will be instantiated instead of ProcToSubComm / SubToProcComm. If `unit_testing`, creates the ut_pipe side-channel. If `finalize_fn`, sends both ProcToSubComm and SubToProcComm objects in to be processed just before set-up is complete. `shutdown` is an optional param in case caller wants multiple sub-processes to share the same shutdown flag. Returns a `t_proc_to_sub` (default: ProcToSubComm) object. When ready to start/run the subprocess, call start() on it. ''' logger = log.get_logger(proc_name, min_log_level=initial_log_level) log_dotted = label.normalize(_DOTTED_FUNCS, 'set_up') if proc_test and proc_test.has(ProcTest.DNE): # This process 'Does Not Exist' right now. # Should we downgrade this to debug, or error out more heavily? # (i.e. exception?) log.group_multi(_LOG_INIT, log_dotted, "'{}' has {}. Skipping creation.", proc_name, proc_test, veredi_logger=logger, log_minimum=log.Level.ERROR, log_success=False) return None # ------------------------------ # Create multiproc IPC stuff. # ------------------------------ log.group_multi(_LOG_INIT, log_dotted, "'{}': Creating inter-process communication...", proc_name, veredi_logger=logger) # The official us<->them IPC pipe. child_pipe, parent_pipe = multiprocessing.Pipe() # The side-channel/unit-test us<->them IPC pipe. ut_child_pipe, ut_parent_pipe = None, None if unit_testing: log.group_multi(_LOG_INIT, log_dotted, "'{}': Creating unit-testing " "inter-process communication...", proc_name, veredi_logger=logger) ut_child_pipe, ut_parent_pipe = multiprocessing.Pipe() context.add('proc-test', proc_test) # multiproc shutdown flag if not shutdown: log.group_multi(_LOG_INIT, log_dotted, "'{}': Creating shutdown inter-process " "event flag...", proc_name, veredi_logger=logger) shutdown = multiprocessing.Event() # ------------------------------ # Create the process's private info. # ------------------------------ log.group_multi(_LOG_INIT, log_dotted, "'{}': Creating process comms objects...", proc_name, veredi_logger=logger) # Info for the proc itself to own. comms = t_sub_to_proc(name=proc_name, config=config, entry_fn=entry_fn, pipe=child_pipe, shutdown=shutdown, debug_flags=debug_flags, ut_pipe=ut_child_pipe) # --- # Updated Context w/ start-up info (SubToProcComm, etc). # --- log.group_multi(_LOG_INIT, log_dotted, "'{}': Saving into the ConfigContext...", proc_name, veredi_logger=logger) ConfigContext.set_log_level(context, initial_log_level) ConfigContext.set_subproc(context, comms) # ------------------------------ # Create the Process, ProcToSubComm # ------------------------------ subp_args = [context] subp_kwargs = {} log.group_multi(_LOG_INIT, log_dotted, "'{}': Creating the sub-process object...", proc_name, veredi_logger=logger) # Create the process object (doesn't start the process). subprocess = multiprocessing.Process( # _subproc_entry() is always the target; it will do some setup and then # call the actual target: `entry_fn`. target=_subproc_entry, name=proc_name, args=subp_args, kwargs=subp_kwargs) # Info for the caller about the proc and how to talk to. proc = t_proc_to_sub(name=proc_name, process=subprocess, pipe=parent_pipe, shutdown=shutdown, ut_pipe=ut_parent_pipe) # ------------------------------ # Use Finalize Callback, if supplied. # ------------------------------ if finalize_fn: log.group_multi(_LOG_INIT, log_dotted, "'{}': Finalize function supplied. " "Calling {}...", proc_name, finalize_fn, veredi_logger=logger) finalize_fn(proc, comms) # ------------------------------ # Return ProcToSubComm for caller to use to communicate to sub-proc. # ------------------------------ log.group_multi(_LOG_INIT, log_dotted, "'{}': Set-up complete.", proc_name, veredi_logger=logger) return proc