Metadata-Version: 2.1
Name: wexample-filestate-symfony
Version: 1.0.2
Summary: Plugs Symfony-aware file-content state declarations into wexample-filestate, applying them through Docker batch operations
Author-Email: weeger <contact@wexample.com>
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Project-URL: homepage, https://github.com/wexample/python-filestate-symfony
Requires-Python: >=3.10
Requires-Dist: attrs>=23.1.0
Requires-Dist: cattrs>=23.1.0
Requires-Dist: wexample-filestate-php>=6.4.7
Requires-Dist: wexample-filestate>=17.0.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Description-Content-Type: text/markdown

# filestate_symfony

Version: 1.0.2

`wexample-filestate-symfony` adds a `SymfonyOption` to the `wexample-filestate` configuration layer, letting developers declare Symfony-specific content rules for files under state control and apply them through Docker batch operations against a running app container. It delegates rule execution to a PHP companion package inside the `{app}_{env}_symfony` container while filestate remains the sole writer, providing drift detection for free. It is aimed at Python developers who use the `wexample-filestate` ecosystem to maintain Symfony applications in Docker and want declarative, version-controlled enforcement of file-content conventions.

## Table of Contents

- [Installation](#installation)
- [Quickstart](#quickstart)
- [Tests](#tests)
- [Architecture](#architecture)
- [Integration in the Suite](#integration-in-the-suite)
- [Dependencies](#dependencies)
- [Versioning & Compatibility Policy](#versioning--compatibility-policy)
- [License](#license)
- [About us](#about-us)
- [Known Limitations & Roadmap](#known-limitations--roadmap)
- [Status & Compatibility](#status--compatibility)
- [Useful Links](#useful-links)
- [Migration Notes](#migration-notes)

## Installation

```bash
pip install wexample-filestate-symfony
```

Requires Python >=3.10.

## Quickstart

```bash
pip install wexample-filestate-symfony
```

This package adds a `symfony` option key to `wexample-filestate`. To activate it, pass `SymfonyOptionsProvider` alongside `DefaultOptionsProvider` when creating the state manager — `DefaultOptionsProvider` supplies the standard keys (`children`, `name`, `should_exist`, …) while `SymfonyOptionsProvider` adds `symfony`:

```python
from wexample_filestate.options_provider.default_options_provider import DefaultOptionsProvider
from wexample_filestate.utils.file_state_manager import FileStateManager
from wexample_filestate_symfony.options_provider.symfony_options_provider import SymfonyOptionsProvider

manager = FileStateManager.create_from_path(
    path="/path/to/symfony/project",
    config={
        "children": [
            {
                "name": "src/Entity/Foo.php",
                "symfony": {},
            }
        ]
    },
    options_providers=[DefaultOptionsProvider, SymfonyOptionsProvider],
)

result = manager.apply()
```

`create_from_path` stores `options_providers` on the root item; every child inherits the list through the parent chain, so the `symfony` key is recognised at any nesting depth.

The `symfony` value may be a dict of sub-options or a list of option names. `SymfonyOption.set_value` normalises the list form:

```python
"symfony": ["option_a", "option_b"]
# stored internally as {"option_a": True, "option_b": True}
```

Passing only `[SymfonyOptionsProvider]` silently drops all default options; always keep `DefaultOptionsProvider` as the first entry.

## Tests

This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.

### Installation

First, install the required testing dependencies:
```bash
.venv/bin/python -m pip install pytest pytest-cov
```

### Basic Usage

Run all tests with coverage:
```bash
.venv/bin/python -m pytest --cov --cov-report=html
```

### Common Commands
```bash
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module

# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing

# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html

# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html

# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
```

### Viewing HTML Reports

After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.

### Coverage Threshold

To enforce a minimum coverage percentage:
```bash
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
```

This will cause the test suite to fail if coverage drops below 80%.

## Architecture

`wexample-filestate-symfony` is a thin extension layer on top of `wexample-filestate`. It consists of three modules and no application logic of its own; the framework drives execution, and Docker carries the work into the container.

### Modules

**src/wexample_filestate_symfony/options_provider/symfony_options_provider.py**

The registration point. `SymfonyOptionsProvider` extends `AbstractOptionsProvider` and returns `[SymfonyOption]` from `get_options()`. Callers pass it to `FileStateManager.create_from_path(options_providers=[DefaultOptionsProvider, SymfonyOptionsProvider])`. Without it, the config layer does not know the `symfony` key exists.

**src/wexample_filestate_symfony/option/symfony_option.py**

The option itself. `SymfonyOption` inherits from three bases:

- `OptionMixin` — scopes, applicability flags, and the `_create_child_required_operation` helper that iterates sub-options.
- `WithBatchDockerOptionMixin` — Docker container lifecycle: spins up a `DockerRunner`, mounts the project root at `/var/www/html`, and runs commands inside the container.
- `AbstractNestedConfigOption` — lets the option hold child config options keyed by name.

`get_scopes()` returns `[Scope.CONTENT]`, so the option acts on file content only. `set_value()` normalises a list input into a dict before storing it:

```python
["option_a", "option_b"]
# becomes
{"option_a": True, "option_b": True}
```

`create_required_operation()` immediately delegates to `_create_child_required_operation()`, which walks `get_allowed_options()` and returns the first operation any sub-option produces. The list of allowed options is currently empty — the hook is in place for Symfony-specific sub-options to be added under `option/symfony/`.

**src/wexample_filestate_symfony/config_value/symfony_config_value.py**

A typed value object. `SymfonyConfigValue` extends `ConfigValue` and is accepted as one of the raw-value types alongside `dict` and `list[str]`. Its `to_option_raw_value()` returns `{}`, and the `raw` field is disabled — it exists so callers can construct a typed value rather than a bare dict when feeding the option programmatically.

### Call path

1. `FileStateManager.create_from_path` stores the provider list on the root item; every child inherits it through the parent chain.
2. The config layer calls `SymfonyOptionsProvider.get_options()` to discover `SymfonyOption`.
3. For each item whose config dict contains `symfony`, the framework instantiates `SymfonyOption` and calls `set_value()` with the raw value.
4. During `manager.apply()`, the framework calls `SymfonyOption.create_required_operation(target, scopes)` for each matched target.
5. `create_required_operation` delegates to `_create_child_required_operation`, which iterates `get_allowed_options()`.
6. When a sub-option produces an operation, `WithBatchDockerOptionMixin._execute_in_docker` ensures the container is running and sends the command into it; the result is written back by `filestate`.

## Integration in the Suite

This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.

### Related Packages

The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.

Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.

## Dependencies

- attrs: >=23.1.0
- cattrs: >=23.1.0
- wexample-filestate-php: >=6.4.7
- wexample-filestate: >=17.0.0

## Versioning & Compatibility Policy

Wexample packages follow **Semantic Versioning** (SemVer):

- **MAJOR**: Breaking changes
- **MINOR**: New features, backward compatible
- **PATCH**: Bug fixes, backward compatible

We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Free to use in both personal and commercial projects.

## About us

[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.

This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.

Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.

## Known Limitations & Roadmap

Current limitations and planned features are tracked in the GitHub issues.

See the [project roadmap](https://github.com/wexample/python-filestate_symfony/issues) for upcoming features and improvements.

## Status & Compatibility

**Maturity**: Production-ready

**Python Support**: >=3.10

**OS Support**: Linux, macOS, Windows

**Status**: Actively maintained

## Useful Links

- **Homepage**: https://github.com/wexample/python-filestate-symfony
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
- **Issue Tracker**: https://github.com/wexample/python-filestate-symfony/issues
- **Discussions**: https://github.com/wexample/python-filestate-symfony/discussions
- **PyPI**: [pypi.org/project/wexample-filestate-symfony](https://pypi.org/project/wexample-filestate-symfony/)

## Migration Notes

When upgrading between major versions, refer to the migration guides in the documentation.

Breaking changes are clearly documented with upgrade paths and examples.
