Skip to main content

CLI tool for generating DDD architecture in Python projects

Project description

PyConstructor ๐Ÿ—๏ธ

Python Version License

PyConstructor is a command-line tool that helps developers quickly create a project structure following Domain-Driven Design (DDD) principles. The tool generates architecture based on a YAML configuration that defines bounded contexts, entities, repositories, services, use cases, and other DDD elements.

๐Ÿš€ Quick Start

Installation

# Install via pip
pip install pyconstructor
# Install via uv
uv add pyconstructor

# Generate YAML file with example data
pyc init

# Edit the generated ddd-config.yaml file
# ...

# Generate structure
pyc run

Basic Usage

  1. Initialize a new project with a preset configuration:
pyc init --preset <PresetType(Optional argument, default to Standard)>
  1. Validate your configuration (Optional command):
pyc validate
  1. Preview the project structure (Optional command):
pyc preview --file <file_name> (Optional argument)
  1. Generate the project:
pyc run --file <file_name> (Optional argument)

๐Ÿ“‹ Available Commands

Core Commands

Command Description Example
init Initialize a new project with a preset configuration pyc init --preset standard
validate Validate your YAML configuration pyc validate --file custom-config.yaml
preview Preview the project structure without generating files pyc preview --file custom-config.yaml
run Generate the project structure pyc run --file custom-config.yaml

Command Options

init Command

# Create project with standard preset
pyc init --preset standard

# Force overwrite existing config
pyc init --preset standard --force

validate Command

# Validate default config (ddd-config.yaml)
pyc validate

# Validate specific config file
pyc validate --file custom-config.yaml

preview Command

# Preview default config
pyc preview

# Preview specific config
pyc preview --file custom-config.yaml

Output:

  • Displays the project structure tree in the console
  • Generates a structure.md file with the same tree view for future reference

Example output:

app/
โ”œโ”€โ”€ domain/
โ”‚   โ”œโ”€โ”€ user/
โ”‚   โ”‚   โ”œโ”€โ”€ entities/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user.py
โ”‚   โ”‚   โ””โ”€โ”€ value_objects/
โ”‚   โ”‚       โ””โ”€โ”€ email.py
โ”‚   โ””โ”€โ”€ catalog/
โ”‚       โ””โ”€โ”€ entities/
โ”‚           โ””โ”€โ”€ product.py
โ”œโ”€โ”€ application/
โ”‚   โ””โ”€โ”€ user/
โ”‚       โ””โ”€โ”€ use_cases/
โ”‚           โ””โ”€โ”€ register_user.py
โ””โ”€โ”€ infrastructure/
    โ””โ”€โ”€ repositories/
        โ””โ”€โ”€ user_repository.py

run Command

# Generate from default config
pyc run

# Generate from specific config
pyc run --file custom-config.yaml

Architecture Presets

PyConstructor comes with three built-in presets:

Simple Preset

Basic DDD structure without bounded contexts:

pyc init --preset simple

Standard Preset

Default preset with bounded contexts:

pyc init --preset standard

Advanced Preset

Complex structure with nested contexts:

pyc init --preset advanced

Configuration

The tool uses YAML configuration files to define your project structure. Example configurations are provided in the src/templates/config_templates directory.

Configuration Reference

Settings Section

settings:
  preset: "standard"  # One of: "simple", "standard", "advanced"
  use_contexts: true  # Whether to use bounded contexts
  contexts_layout: "flat"  # One of: "flat", "nested"
  group_components: true  # Group similar components in directories
  init_imports: false  # Initialize imports in __init__.py files
  root_name: "src"  # Root directory name

Simple Configuration Example

settings:
  preset: "simple"

layers:
  domain:
    entities: User, Product
    value_objects: Email, Price

Standard Configuration Example

settings:
  preset: "standard"

layers:
  domain:
    contexts:
      - name: user
        entities: [User, Profile]
        value_objects: [Email, Password]
      - name: catalog
        entities: [Product, Category]

Advanced Configuration Example (for microservice architecture)

settings:
  preset: "advanced"

layers:
  contexts:
    - name: user_context
      domain:
        entities: User
        value_objects: Email
      application:
        use_cases: CreateUser
      infrastructure:
        repositories: UserRepository

    - name: payment_context
      domain:
        entities: Payment
      application:
        use_cases: ProcessPayment
      infrastructure:
        repositories: TransactionRepository

Complete Configuration Example

Here's a complete example showing all available options:

settings:
  preset: "advanced"
  use_contexts: true
  contexts_layout: "nested"
  group_components: true
  init_imports: true
  root_name: "src"

layers:
  contexts:
    - name: user_context
      domain:
        entities: User, Profile
        value_objects: Email, Password, UserRole
        aggregates: UserAggregate
        repositories: UserRepository
        services: UserService
      application:
        use_cases: CreateUser, UpdateUser, DeleteUser
        commands: CreateUserCommand, UpdateUserCommand
        queries: GetUserQuery, ListUsersQuery
        events: UserCreatedEvent, UserUpdatedEvent
        dtos: UserDTO, UserCreateDTO
        mappers: UserMapper
      infrastructure:
        repositories: UserRepositoryImpl
        services: UserServiceImpl
      interface:
        controllers: [UserController]
        middleware: AuthMiddleware

    - name: order_context
      domain:
        entities: Order, OrderItem
        value_objects: Money, OrderStatus
        aggregates: OrderAggregate
        repositories: OrderRepository
        services: OrderService
      application:
        use_cases: CreateOrder, UpdateOrder
        commands: CreateOrderCommand
        queries: GetOrderQuery
        events: OrderCreatedEvent
        dtos: OrderDTO
        mappers: OrderMapper
      infrastructure:
        repositories: OrderRepositoryImpl
      interface:
        controllers: OrderController

Generated Structure

When using the advanced configuration above, the tool will generate a structure like this:

src/
โ”œโ”€โ”€ user_context/
โ”‚   โ”œโ”€โ”€ domain/
โ”‚   โ”‚   โ”œโ”€โ”€ entities/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ user.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ profile.py
โ”‚   โ”‚   โ”œโ”€โ”€ value_objects/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ email.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ password.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_role.py
โ”‚   โ”‚   โ”œโ”€โ”€ aggregates/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_aggregate.py
โ”‚   โ”‚   โ”œโ”€โ”€ repositories/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_repository.py
โ”‚   โ”‚   โ””โ”€โ”€ services/
โ”‚   โ”‚       โ””โ”€โ”€ user_service.py
โ”‚   โ”œโ”€โ”€ application/
โ”‚   โ”‚   โ”œโ”€โ”€ use_cases/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ create_user.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ update_user.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ delete_user.py
โ”‚   โ”‚   โ”œโ”€โ”€ commands/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ create_user_command.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ update_user_command.py
โ”‚   โ”‚   โ”œโ”€โ”€ queries/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ get_user_query.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ list_users_query.py
โ”‚   โ”‚   โ”œโ”€โ”€ events/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ user_created_event.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_updated_event.py
โ”‚   โ”‚   โ”œโ”€โ”€ dtos/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ user_dto.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_create_dto.py
โ”‚   โ”‚   โ””โ”€โ”€ mappers/
โ”‚   โ”‚       โ””โ”€โ”€ user_mapper.py
โ”‚   โ”œโ”€โ”€ infrastructure/
โ”‚   โ”‚   โ”œโ”€โ”€ repositories/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user_repository_impl.py
โ”‚   โ”‚   โ””โ”€โ”€ services/
โ”‚   โ”‚       โ””โ”€โ”€ user_service_impl.py
โ”‚   โ””โ”€โ”€ interface/
โ”‚       โ”œโ”€โ”€ controllers/
โ”‚       โ”‚   โ””โ”€โ”€ user_controller.py
โ”‚       โ””โ”€โ”€ middleware/
โ”‚           โ””โ”€โ”€ auth_middleware.py
โ””โ”€โ”€ order_context/
    โ””โ”€โ”€ ... (similar structure)

Customizing Templates

You can customize the generated files by modifying the templates in the src/templates directory. Each component type has its own template file that you can modify to suit your needs.

FAQ

Getting Started

Q: Which preset should I choose for my project? A:

  • Simple: Perfect for learning DDD or small projects without complex contexts
  • Standard: Best for most real-world projects with clear bounded contexts
  • Advanced: Use for microservices architecture or when you need maximum flexibility

Q: What happens if files already exist in my project? A: PyConstructor adds new files and directories to your existing structure without touching existing files. This means:

  • New components will be created alongside existing ones
  • Existing __init__.py files won't be modified
  • You can safely run it on existing projects

Q: Can I see what will be generated before actually creating files? A: Yes! Use the preview command:

pyc preview
# or
pyc preview --file your-config.yaml

This shows the complete directory structure in console and generates a structure.md file.

Configuration

Q: How do I add more components after initial generation? A: Simply:

  1. Edit your YAML configuration file to add new components
  2. Run pyc run again - it will add only the new components
  3. Existing files remain untouched

Q: Can I customize the generated code templates? A: Yes, but it's not officially supported yet. Templates are located in src/templates/. Modifying them directly will affect all generations. Official template customization API is planned.

Q: What's the difference between 'flat' and 'nested' context layouts? A:

  • Flat: src/domain/user_context/entities/ (contexts inside layers)
  • Nested: src/user_context/domain/entities/ (layers inside contexts)

Troubleshooting

Q: I get "Configuration file not found" error A: Make sure you have a ddd-config.yaml file in your current directory, or specify the path:

pyc run --file path/to/your/config.yaml

Q: YAML validation fails with cryptic errors A: Common issues:

  • Incorrect indentation (use spaces, not tabs)
  • Missing quotes around special characters
  • Empty values should be written as [] or omitted entirely

Q: Generated code doesn't follow my coding standards A: Currently, PyConstructor generates basic templates. You can:

  • Modify templates in src/templates/ (advanced users)
  • Use code formatters (black, ruff) after generation

Integration

Q: Can I use this with existing projects? A: Yes! PyConstructor safely adds new structure to existing projects:

  • Creates new directories and files without touching existing ones
  • Preserves your current codebase
  • Perfect for gradually introducing DDD structure
  • Just make sure your config doesn't conflict with existing file names

Roadmap & Limitations

Q: What features are planned for future releases? A:

  • Custom template support
  • Framework-specific generators (FastAPI, Django)
  • Interactive configuration builder
  • Migration tools for existing codebases
  • Advanced DDD patterns support

๐Ÿค Contributing

Contributions are welcome. Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git switch -c feature/amazing-feature)
  3. Run tests (pytest)
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

๐Ÿ“„ License

This project is licensed under the MIT Licenseโ€”see the LICENSE file for details.

๐Ÿ‘ค Author

Grigoriy Sokolov (Sokolov_Gr@proton.me)

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

pyconstructor-0.2.2.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyconstructor-0.2.2-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file pyconstructor-0.2.2.tar.gz.

File metadata

  • Download URL: pyconstructor-0.2.2.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pyconstructor-0.2.2.tar.gz
Algorithm Hash digest
SHA256 1ff67e11d91c80040c784f8ed0cbaa3bde4b6fd36de9231735ac49c6c5e82571
MD5 01050c0595e5e57b581d41e315ad672f
BLAKE2b-256 1e4e1f3011d902f04f6d121c56d7eee5515b148d7e1f55c99d0063db2a9565fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyconstructor-0.2.2.tar.gz:

Publisher: publish.yaml on SokolovG/PyConstruct

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyconstructor-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: pyconstructor-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pyconstructor-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 edf23dc26d1ef6f023130a37cd3c81350e5004daacf06d2d6f742a07d21b5ad0
MD5 68b49a9c3ac3873c605d622fa198feee
BLAKE2b-256 746169b586a48548f728c08d768632a888393ea8e57640dea6574337a8281a83

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyconstructor-0.2.2-py3-none-any.whl:

Publisher: publish.yaml on SokolovG/PyConstruct

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page