### Install Protean Source: https://docs.proteanhq.com/guides/getting-started/tutorial/01-your-first-aggregate Install the Protean library using pip. This is the first step to start building your domain. ```bash mkdir bookshelf cd bookshelf pip install protean ``` -------------------------------- ### Initialize Domain with In-Memory Infrastructure Source: https://docs.proteanhq.com/why-protean Start with zero setup for in-memory database, broker, and cache. No Docker or configuration files are needed for initial development. ```python domain = Domain() # In-memory database, in-memory broker, in-memory cache # No Docker, no services, no configuration files ``` -------------------------------- ### Setup Database Tables Source: https://docs.proteanhq.com/reference/cli/data/database Creates all database artifacts for every configured provider, including aggregates, entities, projections, and outbox tables. Run this before starting the server for the first time or after modifying your domain model. ```bash protean db setup --domain=my_domain ``` ```bash protean db setup --domain=my_package.domain ``` -------------------------------- ### Single Real Database Test Setup (PostgreSQL Example) Source: https://docs.proteanhq.com/patterns/setting-up-and-tearing-down-database-for-tests Configures the test environment for a single real database (e.g., PostgreSQL). DomainFixture handles schema creation during setup and drops it during teardown. Data is reset after each test. ```python # tests/conftest.py import pytest from protean.integrations.pytest import DomainFixture from myapp import domain @pytest.fixture(scope="session") def app_fixture(): """Create schema once for the entire test session.""" domain.config["databases"]["default"] = { "provider": "protean.adapters.repository.sqlalchemy.SAProvider", "database_uri": "postgresql://postgres:postgres@localhost:5432/myapp_test", } domain.config["event_processing"] = "sync" domain.config["command_processing"] = "sync" fixture = DomainFixture(domain) fixture.setup() # domain.init() + create schema yield fixture fixture.teardown() # drop schema @pytest.fixture(autouse=True) def _ctx(app_fixture): """Reset data after every test.""" with app_fixture.domain_context(): # resets all data on exit yield ``` -------------------------------- ### Install Protean Source: https://docs.proteanhq.com/reference/testing/conformance Install the Protean library using pip. This is the first step before setting up your adapter for testing. ```bash pip install protean ``` -------------------------------- ### Create Project Directory and Install Protean Source: https://docs.proteanhq.com/guides/getting-started/es-tutorial/01-the-faithful-ledger Set up a new directory for your project and install the Protean library using pip. ```bash mkdir fidelis cd fidelis pip install protean ``` -------------------------------- ### Create Project with Example Code Source: https://docs.proteanhq.com/reference/cli/project/new Include example domain code (aggregate, commands, events, handlers) when creating a new project using the -d include_example=true flag. ```bash protean new authentication \ -d include_example=true \ --defaults ``` -------------------------------- ### Skip Setup Commands Source: https://docs.proteanhq.com/reference/cli/project/new Use `--skip-setup` to skip running setup commands after project initialization. This is useful for testing purposes. ```bash protean new --skip-setup my-project ``` -------------------------------- ### Start Protean Server Source: https://docs.proteanhq.com/guides/server/outbox Start the Protean server to enable the outbox processor. ```bash $ protean server --domain=my_domain ``` -------------------------------- ### Start Protean Server CLI Source: https://docs.proteanhq.com/guides/server Use the `protean server` command to start the server. Specify the domain path or module path as needed. ```bash protean server [OPTIONS] ``` ```bash # Start with domain in current directory protean server ``` ```bash # Start with specific domain path protean server --domain=src/my_domain ``` ```bash # Start with module path protean server --domain=my_package.my_domain ``` ```bash # Start with specific instance protean server --domain=my_domain:custom_domain ``` -------------------------------- ### Install FastAPI and Uvicorn Source: https://docs.proteanhq.com/guides/getting-started/tutorial/10-api Install the necessary packages for building a FastAPI application. ```bash pip install fastapi uvicorn ``` -------------------------------- ### Start Development Environment with Make Source: https://docs.proteanhq.com/community/contributing/testing Command to start the Docker Compose development environment. This brings up all defined services, including databases and caches, for local testing. ```bash make up ``` -------------------------------- ### Install uv and Development Dependencies Source: https://docs.proteanhq.com/community/contributing/setup Install the uv package manager and then sync all development dependencies, including extras and all groups. uv will create a virtual environment in .venv. ```bash $ curl -LsSf https://astral.sh/uv/install.sh | sh $ uv sync --all-extras --all-groups ``` -------------------------------- ### Quick Project Setup with Defaults Source: https://docs.proteanhq.com/reference/cli/project/new Use the --defaults flag to quickly create a project with all default options pre-selected. ```bash protean new my_project --defaults ``` -------------------------------- ### Create Project with Configuration Data Source: https://docs.proteanhq.com/reference/cli/project/new Initialize a project with specific configuration parameters like author details, database type, and broker. ```bash protean new authentication \ -d author_name="John Doe" \ -d author_email=john@example.com \ -d database=postgresql \ -d broker=redis ``` -------------------------------- ### Start Multiple Worker Processes Source: https://docs.proteanhq.com/reference/server/supervisor Use the 'protean server' command with the --workers flag to specify the number of worker processes to start. This example starts 4 workers. ```bash protean server --domain=my_domain --workers 4 ``` -------------------------------- ### Start Protean Server and API Source: https://docs.proteanhq.com/guides/getting-started/tutorial/12-going-async To verify asynchronous processing, start the Protean server in one terminal and the API (e.g., uvicorn) in another. This setup allows the server to pick up commands from the stream. ```bash # Terminal 1 — start the server $ protean server --domain bookshelf ``` ```bash # Terminal 2 — start the API $ uvicorn bookshelf.api:app --reload ``` -------------------------------- ### Running the Protean Hello World Example Source: https://docs.proteanhq.com/guides/getting-started/hello This command shows how to execute the 'hello.py' script to see the Protean aggregate creation, saving, and loading process in action. The output includes the created task details and its unique ID. ```bash $ python hello.py Created: Buy groceries (done=False) Loaded: Buy groceries (done=False) ID: 5eb04301-f191-4bca-9e49-8e5a948f07f6 ``` -------------------------------- ### Run MessageDB with Docker Source: https://docs.proteanhq.com/guides/change-state/event-store-setup Starts a MessageDB instance using Docker. This is required for production event store setups. ```bash docker run -d -p 5433:5432 ethangarofolo/message-db:1.2.6 ``` -------------------------------- ### Initialize Domain and Run Example Source: https://docs.proteanhq.com/guides/getting-started/tutorial/15-fact-events Initialize the Protean domain and execute a scenario demonstrating adding a book, updating its price, and reading the generated fact events from the event store. ```python domain.init(traverse=False) if __name__ == "__main__": with domain.domain_context(): book_repo = domain.repository_for(Book) # Add a book — triggers both the BookAdded event and a fact event print("=== Adding a Book ===") gatsby = Book.add_to_catalog( title="The Great Gatsby", author="F. Scott Fitzgerald", isbn="9780743273565", price=12.99, ) book_repo.add(gatsby) # Update price — triggers a new fact event with complete state print("\n=== Updating Price ===") gatsby.update_price(15.99) book_repo.add(gatsby) # Read fact events from the event store fact_stream = f"{Book.meta_.stream_category}-fact-{gatsby.id}" fact_messages = domain.event_store.store.read(fact_stream) print(f"\nFact events in stream: {len(fact_messages)}") for msg in fact_messages: event = msg.to_domain_object() print(f" Title: {event.title}, Price: ${event.price}") assert len(fact_messages) == 2 # One per state change last_fact = fact_messages[-1].to_domain_object() assert last_fact.price == 15.99 assert last_fact.title == "The Great Gatsby" print("\nAll checks passed!") ``` -------------------------------- ### Initialize Domain and Run Example Source: https://docs.proteanhq.com/guides/getting-started/tutorial/07-projections Initializes the Protean domain and demonstrates adding books, querying the `BookCatalog` projection, and updating a book's price. This section shows how events automatically update the projection and how to interact with the read-optimized view. ```python domain.init(traverse=False) if __name__ == "__main__": with domain.domain_context(): book_repo = domain.repository_for(Book) # Add books — events trigger the projector print("=== Adding Books ===") gatsby = Book.add_to_catalog( title="The Great Gatsby", author="F. Scott Fitzgerald", isbn="9780743273565", price=12.99, ) book_repo.add(gatsby) brave = Book.add_to_catalog( title="Brave New World", author="Aldous Huxley", isbn="9780060850524", price=14.99, ) book_repo.add(brave) orwell = Book.add_to_catalog( title="1984", author="George Orwell", isbn="9780451524935", price=11.99, ) book_repo.add(orwell) # Query the projection — optimized for browsing print("\n=== Book Catalog (Projection) ===") catalog = domain.view_for(BookCatalog) all_entries = catalog.query.all() print(f"Total entries: {all_entries.total}") for entry in all_entries.items: print(f" {entry.title} by {entry.author} — ${entry.price}") # Update a price — projector updates the catalog print("\n=== Updating Price ===") gatsby.update_price(15.99) book_repo.add(gatsby) updated_entry = catalog.get(gatsby.id) print(f"Updated: {updated_entry.title} — ${updated_entry.price}") # Verify assert all_entries.total == 3 assert updated_entry.price == 15.99 print("\nAll checks passed!") ``` -------------------------------- ### Initialize Protean Domain with Auto-Logging Configuration Source: https://docs.proteanhq.com/guides/server/logging Call `domain.init()` to automatically configure Protean's structured logging. This setup detects the environment and installs correlation ID injection. ```python from protean import Domain domain = Domain() domain.init() # auto-configures logging ``` -------------------------------- ### Full Protean Domain Setup Source: https://docs.proteanhq.com/guides/getting-started/es-tutorial/07-reacting-to-events Complete source code for a Protean domain including events, aggregates, commands, and handlers. This provides a foundational example for building event-driven systems. ```python from protean import Domain, apply, handle, invariant from protean.exceptions import ValidationError from protean.fields import Float, Identifier, String from protean.utils.globals import current_domain domain = Domain("fidelis") @domain.event(part_of="Account") class AccountOpened: account_id: Identifier(required=True) account_number: String(required=True) holder_name: String(required=True) opening_deposit: Float(required=True) @domain.event(part_of="Account") class DepositMade: account_id: Identifier(required=True) amount: Float(required=True) reference: String() @domain.event(part_of="Account") class WithdrawalMade: account_id: Identifier(required=True) amount: Float(required=True) reference: String() @domain.event(part_of="Account") class AccountClosed: account_id: Identifier(required=True) reason: String() @domain.aggregate(is_event_sourced=True) class Account: account_number: String(max_length=20, required=True) holder_name: String(max_length=100, required=True) balance: Float(default=0.0) status: String(max_length=20, default="ACTIVE") @invariant.post def balance_must_not_be_negative(self): if self.balance is not None and self.balance < 0: raise ValidationError( {"balance": ["Insufficient funds: balance cannot be negative"]} ) @invariant.post def closed_account_must_have_zero_balance(self): if self.status == "CLOSED" and self.balance != 0: raise ValidationError( {"status": ["Cannot close account with non-zero balance"]} ) @classmethod def open(cls, account_number: str, holder_name: str, opening_deposit: float): account = cls._create_new() account.raise_( AccountOpened( account_id=str(account.id), account_number=account_number, holder_name=holder_name, opening_deposit=opening_deposit, ) ) return account def deposit(self, amount: float, reference: str = None) -> None: if amount <= 0: raise ValidationError({"amount": ["Deposit amount must be positive"]}) self.raise_( DepositMade( account_id=str(self.id), amount=amount, reference=reference, ) ) def withdraw(self, amount: float, reference: str = None) -> None: if amount <= 0: raise ValidationError({"amount": ["Withdrawal amount must be positive"]}) self.raise_( WithdrawalMade( account_id=str(self.id), amount=amount, reference=reference, ) ) def close(self, reason: str = None) -> None: self.raise_( AccountClosed( account_id=str(self.id), reason=reason, ) ) @apply def on_account_opened(self, event: AccountOpened): self.id = event.account_id self.account_number = event.account_number self.holder_name = event.holder_name self.balance = event.opening_deposit self.status = "ACTIVE" @apply def on_deposit_made(self, event: DepositMade): self.balance += event.amount @apply def on_withdrawal_made(self, event: WithdrawalMade): self.balance -= event.amount @apply def on_account_closed(self, event: AccountClosed): self.status = "CLOSED" @domain.command(part_of=Account) class OpenAccount: account_number: String(required=True) holder_name: String(required=True) opening_deposit: Float(required=True) ``` -------------------------------- ### Post-Initialization Invariant Check Source: https://docs.proteanhq.com/guides/domain-behavior/invariants Ensures an aggregate starts in a valid state immediately after initialization. This example shows an Order object failing validation because the total amount does not match the sum of item prices. ```python In [1]: Order( ...: customer_id="1", ...: order_date="2020-01-01", ...: total_amount=100.0, ...: status="PENDING", ...: items=[ ...: OrderItem(product_id="1", quantity=2, price=10.0, subtotal=20.0), ...: OrderItem(product_id="2", quantity=3, price=20.0, subtotal=60.0), ...: ], ... חיצוני:) ERROR: Error during initialization: {'_entity': ['Total should be sum of item prices']} ... ValidationError: {'_entity': ['Total should be sum of item prices']} ``` -------------------------------- ### Running the Complete System with Docker and Protean CLI Source: https://docs.proteanhq.com/guides/getting-started/tutorial/22-full-picture This sequence of commands outlines the steps to set up and run a complete Protean system in production. It includes starting infrastructure services, setting up the database, and launching the Protean server, API, and observatory. ```bash # 1. Start infrastructure docker run -d --name bookshelf-db -e POSTGRES_DB=bookshelf -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:15 docker run -d --name bookshelf-redis -p 6379:6379 redis:7-alpine # 2. Set up the database export PROTEAN_DOMAIN=bookshelf protean database setup # 3. Start the async processing server protean server & # 4. Start the API uvicorn bookshelf.api:app --host 0.0.0.0 --port 8000 & # 5. Start the observatory (optional) protean observatory --port 9000 & ``` -------------------------------- ### Start with DDD Application Service Source: https://docs.proteanhq.com/why-protean This snippet shows a basic application service for creating a post using Domain-Driven Design (DDD) principles. It requires no special setup beyond defining the domain and repository. ```python @domain.application_service(part_of=Post) class PostService: @use_case def create_post(self, title: str, body: str) -> str: post = Post(title=title, body=body) current_domain.repository_for(Post).add(post) return post.id ``` -------------------------------- ### Consuming Custom Repository Methods Source: https://docs.proteanhq.com/patterns/model-reference-data Access reference data through the custom repository to get typed lists or maps. This example shows how to retrieve a list of currencies and a map of currency codes, and how to use the map for validation. ```python repo = current_domain.repository_for(Currency) currencies = repo.all_active() # list[Currency] by_code = repo.as_map() # {"USD": Currency(...), "EUR": ...} if command.currency not in by_code: raise ValidationError({"currency": ["Unknown currency"]}) ``` -------------------------------- ### Running the Protean Quickstart Script Source: https://docs.proteanhq.com/guides/getting-started/quickstart The command to execute the Python script that demonstrates the Protean domain cycle. Shows the expected output for creating and publishing a post. ```bash $ python blog.py Post: Hello, Protean! (status: DRAFT) Post published: Hello, Protean! Updated: Hello, Protean! (status: PUBLISHED) ``` -------------------------------- ### Setup Outbox Table Source: https://docs.proteanhq.com/guides/server/outbox Use this command to create all necessary tables, including the outbox table, for a new domain. ```bash $ protean db setup --domain=my_domain ``` -------------------------------- ### Fragile Asynchronous Test Setup Source: https://docs.proteanhq.com/patterns/testing-event-driven-flows This example demonstrates a fragile approach to testing event-driven flows by relying on fixed time sleeps. This method is prone to flakiness on different environments and can lead to slow test suites. ```python # FRAGILE: How long do we sleep? Too short and the test is flaky. # Too long and the suite is slow. def test_order_flow(self): domain.process(PlaceOrder(...)) time.sleep(2) # Hope the engine processes everything... time.sleep(3) # ...maybe add more time for slow CI... projection = domain.repository_for(OrderDashboard).get("ord-123") assert projection.status == "placed" # Fails intermittently ``` -------------------------------- ### Install Protean with Redis Support Source: https://docs.proteanhq.com/reference/adapters/broker/redis Install the Protean library with Redis broker support using pip. Alternatively, install the `redis` package separately if Protean is already installed. ```bash # Install Protean with Redis support pip install "protean[redis]" # Or install Redis package separately pip install redis>=5.0.0 ``` -------------------------------- ### Set Up Projection Database Source: https://docs.proteanhq.com/reference/troubleshooting For projections that rely on a database, execute `domain.setup_database()` within a domain context to initialize the necessary schema. ```python with domain.domain_context(): domain.setup_database() ``` -------------------------------- ### Install Elasticsearch Provider Source: https://docs.proteanhq.com/reference/adapters/database/elasticsearch Install the Elasticsearch provider using pip. You can install it as part of the Protean package or separately. ```bash pip install "protean[elasticsearch]" # Or install packages separately pip install elasticsearch elasticsearch-dsl ``` -------------------------------- ### Running the Protean Tutorial Script Source: https://docs.proteanhq.com/guides/getting-started/es-tutorial/01-the-faithful-ledger Shows the expected output when running the Python script that demonstrates account creation and persistence. ```bash $ python fidelis.py Created: Alice Johnson (ACC-001) ID: 5eb04301-f191-4bca-9e49-8e5a948f07f6 Balance: $1000.00 Retrieved: Alice Johnson Balance: $1000.00 Version: 0 All checks passed! ``` -------------------------------- ### Install Redis Cache Adapter Source: https://docs.proteanhq.com/reference/adapters/cache/redis Install the Redis cache adapter using pip. You can install it as part of Protean or separately. ```bash pip install "protean[redis]" # Or install the Redis package separately pip install redis>=5.0.0 ``` -------------------------------- ### Install PostgreSQL Provider Source: https://docs.proteanhq.com/reference/adapters/database/postgresql Installs the PostgreSQL provider and the psycopg2-binary package for out-of-the-box compatibility. For production, consider installing psycopg2 from source. ```bash pip install "protean[postgresql]" ``` ```bash pip install psycopg2 ``` -------------------------------- ### Account Dashboard Example Usage Source: https://docs.proteanhq.com/guides/getting-started/es-tutorial/06-account-dashboard Demonstrates opening an account, making a deposit, and then querying the account dashboard projection. ```python if __name__ == "__main__": with domain.domain_context(): # Open an account with $1000 account_id = domain.process( OpenAccount( account_number="ACC-001", holder_name="Alice Johnson", opening_deposit=1000.00, ) ) print(f"Account opened: {account_id}") # Make a deposit domain.process( MakeDeposit( account_id=account_id, amount=500.00, reference="paycheck", ) ) print("Deposit of $500.00 made") # Check the projection via the read-only view summary = current_domain.view_for(AccountSummary).get(account_id) print("\n=== Account Dashboard ===") print(f"Account: {summary.account_number}") print(f"Holder: {summary.holder_name}") print(f"Balance: ${summary.balance:.2f}") print(f"Transactions: {summary.transaction_count}") print(f"Last activity: {summary.last_transaction_at}") assert summary.balance == 1500.00 assert summary.transaction_count == 2 print("\nAll checks passed!") ``` -------------------------------- ### Set up the outbox table Source: https://docs.proteanhq.com/guides/server/external-event-dispatch Run this command to set up the necessary outbox table for your domain. ```bash protean db setup --domain my_domain ``` -------------------------------- ### Install message-db-py Source: https://docs.proteanhq.com/reference/adapters/eventstore/message-db Install the Python client for Message DB using pip. ```bash pip install message-db-py ``` -------------------------------- ### Set up Docker Services for Full Test Suite Source: https://docs.proteanhq.com/community/contributing/setup Start dependent services like redis, elasticsearch, and postgres using 'make up' and 'docker-compose up -d'. ```bash $ make up ... docker-compose up -d redis elasticsearch postgres message-db [+] Running 4/4 ✔ Container protean-postgres-1 Running ✔ Container protean-elasticsearch-1 Running ✔ Container protean-message-db-1 Running ✔ Container protean-redis-1 Running ... ``` -------------------------------- ### Domain Initialization with Database Configuration Source: https://docs.proteanhq.com/concepts/ports-and-adapters Demonstrates how to configure a database connection during Domain initialization. If the connection fails, Protean halts with a ConfigurationError. ```python from protean import Domain domain = Domain() # Non-existent database domain.config["databases"]["default"] = { "provider": "postgresql", "database_uri": "postgresql://postgres:postgres@localhost:5444/foobar", # } domain.init(traverse=False) # Output # # protean.exceptions.ConfigurationError: # Could not connect to database at postgresql://postgres:postgres@localhost:5444/foobar ``` -------------------------------- ### Running Protean Docs Preview Source: https://docs.proteanhq.com/reference/cli/project/docs Execute this command to initiate the live preview server for your project's documentation. The server will typically be accessible at http://localhost:8000. ```bash protean docs preview ``` -------------------------------- ### Install Pre-commit Hooks Source: https://docs.proteanhq.com/community/contributing/setup Install the pre-commit framework to automatically run checks before committing. ```bash $ pre-commit install --install-hooks ``` -------------------------------- ### Install Protean Source: https://docs.proteanhq.com/guides/getting-started/installation Install the Protean library using pip within your activated virtual environment. ```bash pip install protean ``` -------------------------------- ### Command Line: Testing with Different Database Configurations Source: https://docs.proteanhq.com/patterns/setting-up-and-tearing-down-database-for-tests Examples of running tests with in-memory, PostgreSQL, and SQLite databases using command-line arguments and environment variables. ```bash # Fast local development (in-memory) pytest tests/ # Integration tests against PostgreSQL TEST_DB=postgresql DATABASE_URL=postgresql://localhost/myapp_test pytest tests/ # Integration tests against SQLite TEST_DB=sqlite pytest tests/ ``` -------------------------------- ### Install DynamoDB Adapter Source: https://docs.proteanhq.com/reference/adapters/database/custom-databases Command to install the custom DynamoDB database adapter package using pip. ```bash pip install protean-dynamodb ``` -------------------------------- ### Start Observatory with Multiple Domains Source: https://docs.proteanhq.com/reference/server/observability Instantiate and run the Observatory to monitor multiple domains. Ensure domain objects like 'identity', 'catalogue', and 'orders' are defined. ```python # Multi-domain monitoring observatory = Observatory(domains=[identity, catalogue, orders]) observatory.run(port=9000) ``` -------------------------------- ### Install Dependencies Source: https://docs.proteanhq.com/guides/fastapi/testing-endpoints Install FastAPI and httpx for testing endpoints. httpx is required for FastAPI's TestClient. ```bash pip install fastapi httpx ``` ```bash uv add fastapi httpx ``` -------------------------------- ### Command Line: Running Tests with Full Infrastructure Source: https://docs.proteanhq.com/patterns/setting-up-and-tearing-down-database-for-tests Examples of running tests with in-memory infrastructure only, or with full production-like infrastructure including database, broker, and event store. ```bash # In-memory only pytest tests/ # Full infrastructure TEST_INFRA=full \ DATABASE_URL=postgresql://localhost/myapp_test \ MESSAGE_DB_URL=postgresql://localhost/message_store \ pytest tests/ ``` -------------------------------- ### Install SQLAlchemy with Protean Source: https://docs.proteanhq.com/reference/adapters/database/sqlite Install Protean with SQLAlchemy support for SQLite. SQLAlchemy is a required dependency for the SQLite provider. ```bash pip install "protean[postgresql]" # Includes SQLAlchemy # -- or -- pip install sqlalchemy ``` -------------------------------- ### Verify Protean Installation with CLI Source: https://docs.proteanhq.com/guides/getting-started/installation Use the Protean CLI command to confirm that Protean has been installed correctly and is accessible. ```bash protean --version ``` -------------------------------- ### Start PostgreSQL with Docker Source: https://docs.proteanhq.com/guides/getting-started/tutorial/08-persistence Run a PostgreSQL instance using Docker. This command sets up a container named `bookshelf-db` with the specified database and password, and maps the default PostgreSQL port. ```bash docker run -d --name bookshelf-db \ -e POSTGRES_DB=bookshelf \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ postgres:15 ``` -------------------------------- ### Example of Auto-Skipped Test Source: https://docs.proteanhq.com/reference/testing/conformance Tests are automatically skipped if the provider lacks required capabilities, as shown in this example output. ```text SKIPPED [1] Provider 'elasticsearch' (ElasticsearchProvider) lacks required capability: raw_queries ``` -------------------------------- ### Initialize a New Project Source: https://docs.proteanhq.com/reference/cli/project/new Use this command to create a new project with a given name. The project name is a required argument. ```bash protean new [OPTIONS] PROJECT_NAME ``` -------------------------------- ### Instantiate Customer with Address Value Objects Source: https://docs.proteanhq.com/patterns/replace-primitives-with-value-objects Example of creating a Customer instance with Address value objects for shipping and billing. Demonstrates how to pass address details during instantiation. ```python customer = Customer( name="Jane Smith", shipping_address=Address( street="123 Main St", city="Springfield", state="IL", postal_code="62701", country="US", ), billing_address=Address( street="456 Oak Ave", city="Chicago", state="IL", postal_code="60601", country="US", ), ) ``` -------------------------------- ### Custom Validator Usage Example Source: https://docs.proteanhq.com/guides/domain-behavior/validations Shows successful validation with a custom email validator and an example of a failed validation. ```python In [1]: Person(name="John", email="john.doe@gmail.com") Out[1]: In [2]: Person(name="Jane", email="jane.doe@.gmail.com") ... ValueError: Invalid Email Address - jane.doe@.gmail.com ``` -------------------------------- ### Initialize Domain and Process Commands Source: https://docs.proteanhq.com/guides/getting-started/es-tutorial/03-commands-and-pipeline Initializes the domain with specific configurations for event and command processing, then demonstrates opening an account, making a deposit, and a withdrawal. ```python domain.init(traverse=False) domain.config["event_processing"] = "sync" domain.config["command_processing"] = "sync" if __name__ == "__main__": with domain.domain_context(): # Open an account via a command account_id = domain.process( OpenAccount( account_number="ACC-001", holder_name="Alice Johnson", opening_deposit=1000.00, ) ) print(f"Account opened: {account_id}") # Make a deposit via a command domain.process( MakeDeposit( account_id=account_id, amount=500.00, reference="paycheck", ) ) # Make a withdrawal via a command domain.process( MakeWithdrawal( account_id=account_id, amount=150.00, reference="groceries", ) ) # Verify the final state repo = domain.repository_for(Account) account = repo.get(account_id) print(f"Account: {account.holder_name}") print(f"Balance: ${account.balance:.2f}") # 1000 + 500 - 150 = 1350 assert account.balance == 1350.00 print("\nAll checks passed!") ``` -------------------------------- ### Get Cache Connection Object Source: https://docs.proteanhq.com/api/ports/cache Get the connection object for the cache. This is an abstract method that must be implemented by subclasses. ```python @abstractmethod def get_connection(self) -> object: """Get the connection object for the cache""" ``` -------------------------------- ### Install External Broker Package Source: https://docs.proteanhq.com/reference/adapters/broker/custom-brokers Install a custom broker package using pip. Ensure the package name is correct. ```bash pip install protean-kafka-broker ``` -------------------------------- ### Install pytest-bdd Source: https://docs.proteanhq.com/guides/testing/application-tests Install pytest-bdd using pip or uv. This is the primary tool for writing application tests in a BDD style. ```bash pip install pytest-bdd ``` ```bash uv add --group test pytest-bdd ``` -------------------------------- ### Add Sample Data to Repository Source: https://docs.proteanhq.com/guides/change-state/retrieve-aggregates Initializes a repository for the Person aggregate and adds several Person instances to it. This sets up the data for subsequent query examples. ```python repository = domain.repository_for(Person) for person in [ Person(name="John Doe", age=38, country="CA"), Person(name="John Roe", age=41, country="US"), Person(name="Jane Doe", age=36, country="CA"), Person(name="Baby Doe", age=3, country="CA"), Person(name="Boy Doe", age=8, country="CA"), Person(name="Girl Doe", age=11, country="CA"), ]: repository.add(person) ``` -------------------------------- ### Install Telemetry Extra Source: https://docs.proteanhq.com/guides/server/hardening Install the telemetry extra for Protean to enable OpenTelemetry metrics. This is a prerequisite for emitting and collecting metrics. ```bash pip install "protean[telemetry]" ``` -------------------------------- ### Start Observatory with Combined Options Source: https://docs.proteanhq.com/reference/cli/runtime/observatory Launches the Observatory with multiple options configured, including multiple domains, custom host and port, a custom title, and debug logging enabled. ```bash protean observatory --domain identity --domain catalogue --host 127.0.0.1 --port 3000 --title "ShopStream Observatory" --debug ``` -------------------------------- ### Factory vs. Domain Service Example Source: https://docs.proteanhq.com/patterns/factory-methods-for-aggregate-creation Illustrates the difference between a factory method for creating an aggregate and a domain service for coordinating logic across existing aggregates. ```python Order.from_cart(items, customer_id) ``` ```python TransferService.validate_and_debit(source, policy, amount) ``` -------------------------------- ### Verify Protean Installation with Python Interpreter Source: https://docs.proteanhq.com/guides/getting-started/installation Import Protean in a Python shell to verify that it can be recognized and used by your Python installation. ```python import protean protean.get_version() ``` -------------------------------- ### Run Conformance Tests with CLI Source: https://docs.proteanhq.com/reference/testing/conformance Use the `test-adapter` command to run conformance tests against a specified provider. This is the quickest way to test any provider. ```bash protean test test-adapter --provider=memory ``` ```bash protean test test-adapter --provider=postgresql \ --uri="postgresql://postgres:postgres@localhost:5432/testdb" ``` ```bash protean test test-adapter --provider=memory \ --capabilities=basic_storage,transactional ``` ```bash protean test test-adapter --provider=postgresql \ --uri="postgresql://localhost/test" -v ```