Metadata-Version: 2.1
Name: wexample-migration
Version: 6.0.21
Author-Email: weeger <contact@wexample.com>
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Requires-Dist: attrs>=23.1.0
Requires-Dist: cattrs>=23.1.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: wexample-filestate>=6.3.0
Requires-Dist: wexample-helpers>=6.8.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
Requires-Dist: pytest>=9.0.2; extra == "dev"
Description-Content-Type: text/markdown

# migration

Version: 6.0.21

## Table of Contents

- [Tests](#tests)
- [Suite Integration](#suite-integration)
- [Dependencies](#dependencies)
- [Versioning](#versioning)
- [License](#license)
- [Suite Integration](#suite-integration)
- [Suite Signature](#suite-signature)
- [Introduction](#introduction)
- [Roadmap](#roadmap)
- [Status Compatibility](#status-compatibility)
- [Useful Links](#useful-links)
- [Migration Notes](#migration-notes)

## 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%.

## 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
- pyyaml: >=6.0
- wexample-filestate: >=6.3.0
- wexample-helpers: >=6.8.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.

## 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.

# 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.

# migration

Version: 0.1.1

## Table of Contents

- [Tests](#tests)
- [Suite Integration](#suite-integration)
- [Dependencies](#dependencies)
- [Versioning](#versioning)
- [License](#license)
- [Suite Integration](#suite-integration)
- [Suite Signature](#suite-signature)
- [Introduction](#introduction)
- [Roadmap](#roadmap)
- [Status Compatibility](#status-compatibility)
- [Useful Links](#useful-links)
- [Migration Notes](#migration-notes)

## 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%.

## 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
- pyyaml: >=6.0
- wexample-filestate: >=1.0.0
- wexample-helpers: >=1.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.

## 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.

# 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.

# Migration System — Design

## Concept

Migration is the temporal counterpart of filestate.

While filestate manages the state of a filesystem at a given point in time, migration manages the **transition between states over time**.

The core idea: a migration describes how to evolve a workdir/app/repo from one version to another, reusing filestate primitives (Options, Operations) whenever possible.

By adding `WithMigrationWorkdirMixin` to a workdir, you declare that it has a versioned lifecycle and supports sequential migrations.

---

## Primary Use Case

The main use case is upgrading an application’s structure/configuration to match a new version of wex.

```
wex migration:run  (executed inside myapp/)
  → AppWorkdir loaded with target_path=myapp/
  → version read from config.yml (e.g. "5.0.0")
  → migrations 5.x → 6.x applied to the directory
  → config.yml updated with the new version
```

---

## Versioning Unit

The main unit of versioning is the **workdir** (or app/repo), not individual files.

* The current version is stored in the app’s `config.yml`
* `config.yml` is the **single source of truth**
* No separate migration state file is required

### Legacy Support

If no version is present in `config.yml`, the system can:

* Fall back to `guess_version()`
* Infer the version from the actual filesystem state

Once detected, the version is written to `config.yml` and normal behavior resumes.

---

## Core Components

### `MigrationContext`

Context object passed to each migration:

```python
class MigrationContext:
    target_path: Path     # root of the target workdir
    current_version: str  # version read from config.yml
    dry_run: bool         # if True, no real changes are applied
```

---

### `AbstractMigration`

Base class for all migrations:

```python
class AbstractMigration:
    VERSION: str          # target version, e.g. "6.0.0"
    DESCRIPTION: str      # free-form documentation

    def apply(self, context: MigrationContext) -> None: ...
    def rollback(self, context: MigrationContext) -> None: ...   # optional
    def is_applicable(self, context: MigrationContext) -> bool: ...  # optional guard
    def guess_version(self, context: MigrationContext) -> bool: ...  # optional (legacy bootstrap)
```

#### Notes

* `apply()` performs the migration
* `rollback()` is optional but recommended when possible
* `is_applicable()` allows conditional execution
* `guess_version()` is used only when no version is available (legacy workdirs)

---

### `MigrationRunner`

Responsible for orchestrating migrations:

* Reads current version from `config.yml`
* If missing, attempts detection via `guess_version()`
* Sorts migrations using semantic versioning
* Applies migrations sequentially where `VERSION > current_version`
* Updates `config.yml` after each successful migration

---

### `FilestateItemMigration`

A specialized migration for declarative transformations using filestate.

It internally creates a `FileStateManager` and applies a filestate config.

```python
class Migration600(FilestateItemMigration):
    VERSION = "6.0.0"

    def get_filestate_config(self, context: MigrationContext) -> dict:
        return {
            "children": [
                {
                    "name": ".wex",
                    "type": "directory",
                    "should_exist": True,
                }
            ]
        }
```

Use this when:

* Creating files/directories
* Enforcing structure
* Applying predictable transformations

---

### `WithMigrationWorkdirMixin`

Mixin used to declare migrations on a workdir:

```python
class AppWorkdir(WithMigrationWorkdirMixin, Workdir):
    def get_migrations(self):
        from .migrations.migration_5_0_0 import Migration500
        from .migrations.migration_6_0_0 import Migration600
        return [Migration500, Migration600]
```

#### Conventions

* Migrations live in a `migrations/` directory:

```
your-package/
  migrations/
    migration_5_0_0.py
    migration_6_0_0.py
```

* They are defined in the **wex package**, not in the target app
* The app itself is unaware of the migration system

---

## Declaring a Migration

Example:

```python
class Migration110(AbstractMigration):
    VERSION = "1.1.0"
    DESCRIPTION = "Rename .wex_config to .wex/config"

    def apply(self, context: MigrationContext) -> None:
        old = context.target_path / ".wex_config"
        new = context.target_path / ".wex" / "config"
        old.rename(new)

    def rollback(self, context: MigrationContext) -> None:
        # optional
        ...

    def guess_version(self, context: MigrationContext) -> bool:
        # legacy detection
        return (context.target_path / ".wex_config").exists()
```

---

## wex Commands

```bash
wex filestate::migration/status    # current version + pending migrations
wex filestate::migration/run       # apply all pending migrations
wex filestate::migration/run -d    # dry-run (no changes written)
wex filestate::migration/rollback  # rollback last applied migration
```

---

## Design Choices (Intentional Constraints)

### No Separate State File

* The version is stored only in `config.yml`
* Avoids duplication and desynchronization
* Keeps the system simple and explicit

---

### No Migration History

* Only the current version is tracked
* No need to store which migrations were applied
* The version itself is sufficient to determine what remains

---

### No YAML DSL for Migrations

* Migrations are inherently procedural (conditions, logic)
* YAML is suited for describing state (filestate), not transformations
* Code remains the source of truth

---

### Version Detection Only for Bootstrap

* `guess_version()` is used only for legacy workdirs
* Once a version is detected and written, it is no longer needed
* Normal operation relies solely on `config.yml`

---

## Inspirations

* **filestate**: Option → Operation pipeline, dry-run, rollback, file/directory modeling
* **Alembic / Django migrations**: sequential execution, version ordering
* **Rector (PHP)**: composable and declarative transformations
* **wex v5 legacy**: `migration_X_Y_Z.py`, version detection patterns (concept reused, implementation redesigned)

## Known Limitations & Roadmap

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

See the [project roadmap](https://github.com/wexample/python-migration/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-migration
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
- **Issue Tracker**: https://github.com/wexample/python-migration/issues
- **Discussions**: https://github.com/wexample/python-migration/discussions
- **PyPI**: [pypi.org/project/migration](https://pypi.org/project/migration/)

## 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.

## Known Limitations & Roadmap

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

See the [project roadmap](https://github.com/wexample/python-migration/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-migration
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
- **Issue Tracker**: https://github.com/wexample/python-migration/issues
- **Discussions**: https://github.com/wexample/python-migration/discussions
- **PyPI**: [pypi.org/project/migration](https://pypi.org/project/migration/)

## 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.
