Type-safe command pattern implementation in pure Python
Project description
Parts of this readme do not render correctly on pypi, see the repository for a better experience
Command System
A type-safe implementation of the command pattern in Python, designed to handle command execution with a lifecycle that includes deferral and cancellation.
With this package, you can create commands that can be queued and manage their own lifecycle, allowing for interacting with external systems, or building your own systems with complex interactions in a safe, clean, and maintainable way.
Example Usage
Simply subclass Command, CommandArgs, and optionally CommandResponse to create a custom command for your use case.
# SayHelloCommand.py
from command_system import (
Command,
CommandArgs,
CommandResponse,
ExecutionResponse,
)
from dataclasses import dataclass
@dataclass
class SayHelloArgs(CommandArgs):
name: str
@dataclass
class SayHelloResponse(CommandResponse):
message: str = ""
class SayHelloCommand(Command[SayHelloArgs, SayHelloResponse]):
ARGS = SayHelloArgs
_response_type = SayHelloResponse
def execute(self) -> ExecutionResponse:
if not self.args.name:
return ExecutionResponse.failure("Name cannot be empty.")
self.response.message = f"Hello, {self.args.name}!"
return ExecutionResponse.success()
You can then use the CommandQueue to submit commands, and then queue.process_once() or queue.process_all() to execute them.
# main.py
from command_system import CommandQueue
from SayHelloCommand import SayHelloCommand, SayHelloArgs
queue = CommandQueue()
response = queue.submit(SayHelloCommand(SayHelloArgs(name="Alice")))
print(response.status) # Pending
queue.process_once()
print(response.status) # Completed
print(response.message) # Hello, Alice!
Command Lifecycle
flowchart TD
A[create command] -->|"queue.submit(command)"| B[responseStatus.CREATED]
B --> C{"command.should_defer()"}
C -->|"DeferResponse.defer()"| W["responseStatus.PENDING"]
W --> C
C -->|"DeferResponse.proceed()"| D{"command.should_cancel()"}
D -->|"CancelResponse.cancel()"| E[ResponseStatus.CANCELED]
D -->|"CancelResponse.proceed()"| F["command.execute()"]
F -->|"ExecutionResponse.success()"| G["ResponseStatus.COMPLETED"]
F -->|"ExecutionResponse.failure()"| H["ResponseStatus.FAILED"]
Creating a command
Subclass CommandArgs and add any arguments your command needs. This class will be used to pass parameters to your command.
[!CAUTION] Don't add your arguments directly to the
Commandclass. The args class is required for command chaining to work in a type-safe manner.
Subclass Command and set the ARGS class attribute to the subclass of CommandArgs you created. Implement the execute method to define the command's behavior.
- You can also override
should_deferandshould_cancelmethods to control the command's lifecycle.
Optionally, you can create a custom response class by subclassing CommandResponse so that your command can return specific type-safe data. If you do this, set the _response_type class attribute of your Command subclass to your custom response class.
Writing your execute method
[!WARNING]
Yourexecutemethod should not return your custom response class directly. Theself.responseattribute is automatically set to an instance of your custom response class, which you should modify instead. Then, return anExecutionResponseinstance to indicate the command's success or failure.
Writing should_defer and should_cancel methods
These methods can be overridden to control the command's lifecycle. They must return a DeferResponse or CancelResponse instance, respectively. You can use them to set conditions for deferring or canceling the command.
Complex Command example
for an example of deferring and canceling commands, see the tests/test_defer_cancel.py file.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file command_system-0.1.1.tar.gz.
File metadata
- Download URL: command_system-0.1.1.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.7.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b69c30ba119fd50cf6406d5dec928a203121ec98151e65c2d9c3e0f7f3f6815
|
|
| MD5 |
bd6ae2b0c021d9fd4f9f7e9ea7d2bb7b
|
|
| BLAKE2b-256 |
e9d325bfb171708414bad1bc604bb5f25606236618f7fba24b51d4538aaeadcb
|
File details
Details for the file command_system-0.1.1-py3-none-any.whl.
File metadata
- Download URL: command_system-0.1.1-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.7.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0444859fdc748830bb0ab1db2a85f5ba7ca9f582ce6fa5c1744248e8fa3d5bf0
|
|
| MD5 |
823727b6f8b142aebb3202eebb426f89
|
|
| BLAKE2b-256 |
81dfa300ff418877d73fa8ae284c6d9db44262f917a9355017247de3c642c659
|