SimService API
- simservice.service_function(func: Callable, function_name: Optional[str] = None)
Service function registrator: makes ad-hoc modifications to the client-side interface
This can be used within service specification to make an internal method available as a method on a client-side service proxy
E.g., if
MyServiceWrap
defines a service wrap, the underlying service of which makes the following specificationdef f(): print("Hello from the server side!")
Then
f()
can be made available on a proxy of the service on the client side by declaring inside the service,service_function(f)
Then on the client side, the following can then be performed:
my_service = MyServiceWrap() my_service.run() my_service.f()
Note that the availability of a service function depends on the specification of the underlying service. At various stages of usage, a service may or may not have yet made a service function available.
- Parameters:
func (Callable) – function to make available
function_name (str) – optional name assignment; if not specified, then the proxy method will be named the same as the registered function. Useful for attaching to methods of the same name to the same service as a service function
- Returns:
None
- simservice.close_service(_s) None
Closes a service completely
- Parameters:
_s – service proxy
- class simservice.ExecutionContext(_proxy, run: bool = True, init: bool = True, start: bool = True, finish: bool = True, close: bool = True)
A context to automate much of the mundane details of managing simple services
- simservice.close()
Closes module managers
- Returns:
None
basics
Defines basic library standard definitions
- simservice.basics.name_mangler(process_name: str, name: str) str
Standard name mangling of this module by process name
- Parameters:
process_name (str) – process name (e.g., hex( os.getpid() ) )
name (str) – name to mangle
- Returns:
mangled name
- Return type:
str
- simservice.basics.standard_process_name() str
Get standard process name
- Returns:
standard process name
- Return type:
str
managers
Defines service managers
- class simservice.managers.ServiceManagerLocal
Manager for locally-hosted services
- function_registry: Dict[str, Callable] = {}
Register of functions
- classmethod is_registered(_name) bool
Tests if a service has been registered
- Parameters:
_name (str) – name of service or function
- Returns:
True if passed name is found in registry
- Return type:
bool
- manager: Optional[_ServiceManagerLocal] = None
Underlying manager
- classmethod register_function(_function_name, _func)
Registers a function with the manager
- Parameters:
_function_name (str) – name of function
_func (Callable) – function to register
- Returns:
None
- classmethod register_service(_service_name, _service_wrap)
Registers a service wrap with the manager
- Parameters:
_service_name (str) – name of service
_service_wrap (service_wraps.TypeProcessWrap) – service wrap to register
- Returns:
None
- service_registry = {}
Registry of services
type: Dict[str, service_wraps.TypeProcessWrap]
- classmethod shutdown()
Shuts down the manager
- classmethod start(*args, **kwargs)
Simple wrap of BaseManager.start
- started: bool = False
Flag for whether the manager has been started
- simservice.managers.close_services()
Closes all service managers
- Returns:
None
messages
Defines messages and inter-process message-passing structures
- class simservice.messages.ConnectionMessage(_command, *args, **kwargs)
Standard message class for function calling between processes via a Pipe
- Parameters:
_command (str or None) – command name
args (tuple) – command positional arguments
kwargs (dict) – command keyword arguments
- TERMINATOR = 'ConnectionMessageTerminator'
Signal code to terminate connection
- property is_terminator: bool
- Returns:
True if this is a terminator message
- Return type:
bool
- static terminator()
- Returns:
standard message to predicate connection termination
- Return type:
- class simservice.messages.Functor
A callable object
- class simservice.messages.RemoteFunctionEvaluator(conn, func=None)
Safe way to evaluate a function in a different process
- Parameters:
conn (multiprocessing.connection.Connection) – RemoteFunctionEvaluator-RemoteFunctionWorker connection, RemoteFunctionEvaluator side
func (Callable or None) – function to evaluate; optional
- class simservice.messages.RemoteFunctionWorker(conn, func, daemon: bool = False)
Safe way to send function evaluations to a different process
Note: this is safer than deriving from multiprocessing.Process, since potential applications include instantiation during bootstrap phase of parent processes
- Parameters:
conn (multiprocessing.connection.Connection) – RemoteFunctionEvaluator-RemoteFunctionWorker connection, RemoteFunctionWorker side
func (Callable) – function to evaluate
daemon (bool) – daemon argument to base Thread class
- run() None
Runs the thread
- class simservice.messages.ServiceFunctionConnectionMessage(service_name: str, function_name: str, evaluator: RemoteFunctionEvaluator)
Standard message class for service function callbacks with a RemoteFunctionEvaluator - RemoteFunctionWorker pair
- Parameters:
service_name (str) – service name
function_name (str) – function name
evaluator (RemoteFunctionEvaluator) – evaluator
- simservice.messages.connection_terminator = <simservice.messages.ConnectionMessage object>
A connection terminator message
- simservice.messages.dispatch_terminate(conn) None
Generic communication protocol: terminate worker side
- Parameters:
conn (multiprocessing.connection.Connection) – dispatcher-worker connection, dispatcher side
- Returns:
None
- simservice.messages.dispatch_transmit(conn, _cmd, *args, **kwargs) Any
Generic communication protocol: dispatcher side
- Parameters:
conn (multiprocessing.connection.Connection) – dispatcher-worker connection, dispatcher side
_cmd (str or None) – function name
args (tuple) – function positional arguments
kwargs (dict) – function keyword arguments
- Returns:
function return value
- Return type:
Any
- simservice.messages.remote_function_factory(_func, daemon: bool = False) Tuple[RemoteFunctionEvaluator, RemoteFunctionWorker]
Generate a pipe to evaluate a function in a different process
Should be generated in the process that defines the function, from which the evaluator can be piped elsewhere
Safe so long as the function and its returned data can be serialized
- Parameters:
_func (Callable) – function
daemon (bool) – daemon argument to RemoteFunctionWorker instance
- Returns:
evaluator-worker pair
- Return type:
- simservice.messages.safe_transmit(conn=None) Callable
Wrap to do communication protocol with safe handling of common exceptions
- Parameters:
conn (multiprocessing.connection.Connection or None; default None) – connection
- Returns:
function wrapper
- simservice.messages.worker_transmit(conn, func) None
Generic communication protocol: worker side
Blocks until routine is terminated by dispatcher
- Parameters:
conn (multiprocessing.connection.Connection) – dispatcher-worker connection, worker side
func (Functor) – functor with supporting evaluation by ConnectionMessage
- Returns:
None
PySimService
Defines the base class for simulation services
- class simservice.PySimService.PySimService(sim_name: str = '', *args, **kwargs)
Client-side interface for simulation service processes Implementations should derive a wrap for an underlying service from this class
Basic usage is
sim = PySimService() sim.run() sim.init() sim.start() for s in range(S): sim.step() sim.finish()
Status reporting is as follows
sim = PySimService() : sim.status -> SimStatus.REGISTERED
sim.run() : sim.status -> SimStatus.SIM_LOADED
sim.init() : sim.status -> SimStatus.SIM_INITIALIZED
sim.start() : sim.status -> SimStatus.SIM_STARTED
sim.step() : sim.status -> SimStatus.SIM_RUNNING
sim.finish() : sim.status -> SimStatus.SIM_FINISHED
sim.stop() : sim.status -> SimStatus.SIM_STOPPED
sim.stop(terminate_sim=False) : sim.status -> SimStatus.SIM_FINISHED
- beginning_step: int
First simulaton step
- property current_step: int
Current simulation step
- property error_message: Optional[str]
Error message to report on demand, if any
- finish() None
Execute underlying simulation finish
- Returns:
None
- init() bool
Initialize underlying simulation
- Returns:
True if started; False if further start calls are required
- Return type:
bool
- static inside_run(self) None
Called inside run; this supports parallel applications
To support running a service in parallel, overload this or set it via
set_inside_run
with what to do when this service acts without further control from the calling process- Parameters:
self (PySimService) – this service instance
- Returns:
None
- property profiler_report: str
Return on-demand profiling information about simulation service
- Returns:
profiling information
- Return type:
str
- run()
Initialize underlying simulation
All prep for the underlying simulation is complete after this call
Returned dictionary contains
name: the name of the simulation
sim: this servce instance
- Returns:
name and reference of this service instance
- set_inside_run(_inside_run_func) None
Set inside run function
- Parameters:
_inside_run_func ((PySimService) -> None) – inside run function
- Returns:
None
- set_sim_name(_sim_name: str) None
Set simulation name after instantiation
- Parameters:
_sim_name (str) – name of the simulation
- Returns:
None
- start() bool
After simulation and before stepping
- Returns:
True if started; False if further start calls are required
- Return type:
bool
- steer() bool
Execute steering; calling signal for ad-hoc changes to service and underlying simulation data
- Returns:
True if OK, False if something went wrong
- Return type:
bool
- step() bool
Execute a step of the underlying simulation
- Returns:
True if successful, False if something failed
- Return type:
bool
- stop(terminate_sim: bool = True) None
Execute underlying stop
- Parameters:
terminate_sim (bool) – Terminates simulation if True; default True
- Returns:
None
- class simservice.PySimService.SimStatus(value)
Simulation status enum
service_containers
Defines containers for service processes
- class simservice.service_containers.ProcessContainer(_conn, _process_cls, *args, **kwargs)
Basic container for a service process
An instance of this class instantiates a service environment and spawns an underlying service process
- Parameters:
_conn (multiprocessing.connection.Connection) – X-process connection, process side
_process_cls – process-launching class; args and kwargs are passed to this to instantiate the process
args – process-launching positional arguments
kwargs – process-launching keyword arguments
- run()
Runs the process
service_factory
Defines a factory method for instantiating services
- class simservice.service_factory.ProcessRegistry
A registry of process info
Acts as a dictionary, where each key is the name of a registered service, and each value is a tuple of the following,
the service process
the service wrap
connection to the service process
connection to service function receiver
- simservice.service_factory.close_service(_s) None
Closes a service completely
- Parameters:
_s – service proxy
- simservice.service_factory.connect_properties(_client_process, _server_wrap_class) None
Connect properties of a wrapped service class to a client process class
Wrapped service class should present a list of properties via a method _property_names() and corresponding getter and setter methods.
E.g., for
p
incls._property_names()
,cls.get_p()
andcls.set_p()
are defined- Parameters:
_client_process – client-side service proxy instance
_server_wrap_class – server-side wrapped service class
- Returns:
None
- simservice.service_factory.get_proxy_by_process_name(_process_name: str)
Returns a process by name
- Parameters:
_process_name (str) – name of process
- Returns:
- Return type:
- simservice.service_factory.process_factory(_service_name: str, *args, **kwargs)
Main template service process proxy generator for local services
Implementations should work through this when presenting a service proxy
- Parameters:
_service_name (str) – basic name of service; the factory will generate a unique name for each instance
args – service constructor position arguments
kwargs – service constructor keyword arguments
- Returns:
service proxy instance
service_wraps
Defines service wraps
- class simservice.service_wraps.TypeProcessWrap(_return_conn, *args, **kwargs)
Process wrap base class
Client service proxies are generated from this wrap
Service implementations should derive a wrap from this and register it with an appropriate service manager
Service wraps with method and property names that collide with those defined on this class will be ignored when generating a client-side proxy class
- close()
Closes the proxy
- process_name() str
Reserved function for uniquely identifying a service process
Do not override
- Returns:
unique process name
- Return type:
str
- simservice.service_wraps.proxy_function_factory(_cmd: str, _conn) partial
Service proxy dispatcher function factory
Generated function goes on client proxy wrap and dispatches commands to service
ProcessContainer
instance- Parameters:
_cmd (str) – function name defined on server-side service wrap
_conn (multiprocessing.connection.Connection) – manager-process connection, manager side
- Returns:
serial-safe dispatch transmiter
- Return type:
functools.partial
- simservice.service_wraps.proxy_property_accessor_factory(_name: str, _conn)
Service proxy dispatcher property factory
- Parameters:
_name (str) – property name
_conn (multiprocessing.connection.Connection) – manager-process connection, manager side
- Returns:
property getter, setter
ServiceFunctionReceiver
Defines structures for connecting service functions
- class simservice.ServiceFunctionReceiver.ServiceFunctionReceiver
Handles callbacks for instantiating service functions of service proxies
Service process sends registered service functions via Pipe
Processing generates service function containers for accessing underlying service function on the client side
Processing is invoked by workers that monitor pipes between the registry in the service process and the receiver in the main process
- KEY_CONN = 'Connection'
Key for connection in container storage dictionary
- KEY_CONT = 'Container'
Key for container in container storage dictionary
- classmethod disconnect_service(service_proxy) None
Remove a service from the receiver.
- Parameters:
service_proxy – service proxy instance
- Returns:
None
- classmethod register_service(service_proxy, service_conn) None
Register service with receiver
A service process should be registered before being deployed, since the receiver must be ready to handle service function callbacks during service process activity
- Parameters:
service_proxy – service proxy instance
service_conn (multiprocessing.connection.Connection) – service function callback connection; receiver side
- Returns:
None
- service_containers = {}
Service container storage
type: Dict[str, Dict[str, Union[multiprocessing.connection.Connection, _ServiceFunctionContainer]]]
- workers: Dict[str, _ServiceFunctionConnectionWorker] = {}
Service function connection worker storage
ServiceFunctionRegistry
Defines the service function interface
- exception simservice.ServiceFunctionRegistry.NotAServiceError
Raised when attempts are made to register a service function outside of a simservice environment
- class simservice.ServiceFunctionRegistry.ServiceFunctionRegistry
Registers service function on service process side and relays them to receiver in main process
- parent = None
Service process; set by parent process during environment setup
If this isn’t set, then this class is being improperly accessed
- process_name: Optional[str] = None
Name of this process; set by parent process during environment setup
- receiver_conn = None
Connection to main process service function receiver; set by parent process during environment setup
type: multiprocessing.connection.Connection
- classmethod register_function(func: Callable, function_name: Optional[str] = None) None
Registers a service function
- Parameters:
func (Callable) – function to register
function_name (str) – name of function on proxy; optional
- Returns:
None
- workers = {}
Worker storage by function name
These calculate service functions on demand by the client side and send them back with threading
type: Dict[str, Tuple[Callable, messages.RemoteFunctionWorker]]
- simservice.ServiceFunctionRegistry.service_function(func: Callable, function_name: Optional[str] = None)
Service function registrator: makes ad-hoc modifications to the client-side interface
This can be used within service specification to make an internal method available as a method on a client-side service proxy
E.g., if
MyServiceWrap
defines a service wrap, the underlying service of which makes the following specificationdef f(): print("Hello from the server side!")
Then
f()
can be made available on a proxy of the service on the client side by declaring inside the service,service_function(f)
Then on the client side, the following can then be performed:
my_service = MyServiceWrap() my_service.run() my_service.f()
Note that the availability of a service function depends on the specification of the underlying service. At various stages of usage, a service may or may not have yet made a service function available.
- Parameters:
func (Callable) – function to make available
function_name (str) – optional name assignment; if not specified, then the proxy method will be named the same as the registered function. Useful for attaching to methods of the same name to the same service as a service function
- Returns:
None
utils
Defines utility features
- class simservice.utils.ExecutionContext(_proxy, run: bool = True, init: bool = True, start: bool = True, finish: bool = True, close: bool = True)
A context to automate much of the mundane details of managing simple services
- class simservice.utils.NonDaemonicContext
A non-daemonic context
- Process
alias of
NonDaemonicProcess
- class simservice.utils.NonDaemonicPool(*args, **kwargs)