<!--
SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
SPDX-License-Identifier: BSD-2-Clause
-->

# Changelog

All notable changes to the feature-check project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [2.3.2] - 2026-03-25

### Fixes

- Python implementation:
    - do not test for the same base feature over and over
    - do not bundle the `.venv` directory into the sdist tarball

### Additions

- Python implementation:
    - tentatively declare Python 3.15 as supported

### Other changes

- Python implementation:
    - use Ruff 0.15.7 with no changes
    - allow pytest 9.x and use the `--strict` option
    - bump some lower dependency constraints for Python 3.15 compatibility
- Rust implementation:
    - drop an obsolete Clippy override
    - note the Clippy arguments are synced with Rust 1.94
    - use execline scripts for build testing
    - drop the `facet-unstable` feature
    - drop `thiserror`, implement `Display` and `Error` ourselves

## [2.3.1] - 2025-10-10

### Fixes

- Documentation:
    - bump some lower version constraints to avoid a segfault with Python 3.14
- Rust implementation:
    - bump the `serde` dependency to 1.0.119 to make sure consumers get compatible
      versions of `serde` and `serde_derive`

### Other changes

- Python implementation:
    - refresh the `uv.lock` file
- Rust implementation:
    - switch to `nom` 8.x, adapt to the `Parser` trait

## [2.3.0] - 2025-10-08

### Compatibility-affecting changes

- Rust implementation:
    - bump MSRV to 1.87

### Fixes

- Python implementation:
    - bump the `hatchling` dependency to handle Python 3.13 and 3.14
    - bump some dependency versions so that `uv sync --resolution=lowest` works
- Rust implementation:
    - make `Version::new()` a const function
    - bump the `serde` dependency to 1.0.115 since we use `transparent`
- Documentation:
    - bump the `mkdocstrings` dependency requirement to 0.26 to fix the build

### Additions

- Python implementation:
    - tentatively declare Python 3.14 as supported
    - add the `tool.uvoxen` section to the `pyproject.toml` file to allow
      testing using the `uvoxen` tool
    - add the `uvoxen-sync-check` test environment to make sure that
      the `tox.ini` file is in sync with the `tool.uvoxen` definitions
    - also keep the `uv.lock` file under version control
    - bump some dependency versions to satisfy `uv --resolution=lowest`
    - add the `run-uvoxen` tool to test with all supported Python versions
- Rust implementation:
    - add the `facet-unstable` crate feature to allow `Version` and
      `VersionComponent` structs to be handled using the `facet` library
- Documentation:
    - add the `publync` section to the top-level `pyproject.toml` file to allow
      `publync` to publish the documentation to the Ringlet homepage

### Other changes

- Python implementation:
    - move the build dependencies from a separate file into the `pyproject.toml` one
    - use PEP 735 dependency groups instead of separate requirement files for
      the test environments
    - use `ruff` 0.14.0, override some more checks and reformat some source code
- Rust implementation:
    - override some more Clippy lints
    - use traits as `_` (anonymously) as possible
    - drop the `test_` prefix for some unit test functions
    - drop some unnecessary semicolons
    - use the canonical name for a `Display::fmt()` implementation's parameter
    - use `Option::then_some()`
    - change the `#[allow(...)]` lint overrides to `#[expect(...)]` and
      specify the reason for each one
    - migrate to the 2024 Rust edition: reformat some `use` statements
    - use `//` comments for the SPDX tags
    - allow `thiserror` 2.x with no changes
    - allow `facet` up to 0.29.x for the `facet-unstable` feature
- Documentation:
    - use the `uvoxen` tool to generate and run the documentation build and
      the SPDX tags check
    - use `reuse` 6.x and `mkdocstrings` 0.30.x with no changes

## [2.2.0] - 2024-07-29

### Fixes

- Python implementation:
    - intercept `pyparsing` errors and raise our own `ParseError` instead
    - handle separate option values starting with a dash by switching to `click` for
      command-line parsing
- Rust implementation:
    - handle separate option values starting with a dash
    - drop useless calls to `format!` when invoking `anyhow!` and `bail!`
- Testing framework:
    - Python:
        - use `minversion`, not `min_version`, to support Tox 3.x for a while longer
        - add some unit tests using the `hypothesis` library
    - Nix expressions:
        - explicitly invoke `python3.X` instead of `python3` to make sure
          the correct Python version is tested even if a "more preferable"
          one is installed within the Nix environment for some reason

### Additions

- Rust implementation:
    - allow the `Version` struct to be deserialized if needed
- Testing framework:
    - test different prefixes for the features line
    - test for separate option values starting with a dash, e.g.
      `feature-check -O --features`

### Other changes

- Python implementation:
    - let Ruff insist on trailing commas
- Rust implementation:
    - simplify a couple of doc references
    - use `clap_derive` and `serde_derive` as separate crates
- Documentation framework:
    - use `mkdocstrings` 0.25 with no changes
- Testing framework:
    - reuse:
        - use reuse 4.x
        - switch from `.reuse/dep5` to `REUSE.toml`
    - Python:
        - Ruff:
            - use Ruff 0.5.5
            - drop the obsolete `ANN101` and `BLE001` overrides
            - globally override the `DOC501` "exception not documented in
              the docstring" check
            - move the base configuration to `python/ruff-base.toml` and
              the full configuration to `python/pyproject.toml`
            - use the concise output format even in preview mode
        - vendor-import vetox 0.1.4
    - Nix expressions:
        - pass the Perl and Python versions as strings
        - only pass the minor Perl and Python versions, we use
          Perl 5.x and Python 3.x
        - use `uv` and `tox-uv` in the vetox test
        - drop the `py-ver` argument from the `perl-tap` expression
        - use Python 3.12 and Perl 5.38 by default

## [2.1.0] - 2024-02-10

### Semi-incompatible changes

- Python implementation:
    - drop support for Python 3.7, 3.8, and 3.9

### Additions

- Start some `MkDocs` documentation and move the changelog file there.
- Python implementation:
    - declare Python 3.12 and (tentatively) 3.13 as supported
    - rename the `VersionComponent.__cmp__()` method to `cmp()`; Python 3.x has
      never had a `__cmp__()` dunder method, so it is better to expose this one
    - provide a `__hash__()` method for `VersionComponent`
- Rust implementation:
    - implement the `IntoIterator` trait for `&Version` for easier looping
- Testing framework:
    - Python:
        - add tags to the Tox environments for the tox-stages tool
        - add the "reuse" test environment to check the SPDX tags
        - import the `vetox` tool for running Tox in a virtual environment and
          add a Nix shell expression for running it with multiple Python versions

### Other changes

- Switch to yearless copyright notices.
- Switch to SPDX copyright and license tags.
- Python implementation:
    - minor improvements and refactoring to make use of Python 3.10's features
    - switch from setuptools to hatchling for the PEP517 build
    - break the installation and test requirements into separate files
    - use Ruff's isort implementation
    - minor improvements and refactoring suggested by Ruff 0.2.1
    - switch from Black to Ruff for source code formatting
- Rust implementation:
    - minor improvements and refactoring suggested by Clippy
    - Clippy: allow blanket restriction lints and the question mark operator
- Testing framework:
    - Python:
        - drop the Python version from the mypy configuration, we have other
          means of testing with multiple Python versions
        - convert the `tox.ini` file to the Tox 4.x format
        - drop the "flake8" and "pylint" test environments in favor of
          the new "ruff" one
        - use mypy 1.x, pytest 8.x, and reuse 2.x with no changes
        - minor improvements to the Nix expressions for running the Python tests
        - run Ruff in preview mode
- fcheck-testdata:
    - use the `anyhow` and `thiserror` crates instead of `expect-exit` and `quick-error`
    - use the `tracing` crate instead of `config-diag`

## [2.0.0] - 2022-10-12

### Incompatible changes

- Rust implementation:
    - the numeric components of version strings are now unsigned (`u32`),
      whereas before a signed integer type (`i32`) was used
    - parse the examined program's features line into `Version` structs
      instead of free-form strings
    - use the `anyhow` and `thiserror` libraries instead of `quick-error`
      and, for the command-line tool, `expect-exit`; the exported enums and
      structs representing errors returned by the library functions have
      been reimplemented
- Python implementation:
    - use frozen dataclasses instead of reimplementing them poorly
    - introduce the `.version.VersionComponent` and `.version.Version` classes
      that provide an easy-to-use interface for parsing and comparing version
      strings
    - store a `BoolOp` object directly into the parsed `ExprOp` instead of
      referring to the former by a string name stored in the latter

### Semi-incompatible changes

- Python implementation:
    - bump the minimum supported Python version to 3.7:
        - use deferred type annotations, allowing us to use the lowercase type
          names instead of the `typing` generics
        - use `subprocess.run(capture_output=True)` instead of `Popen`
- Rust implementation:
    - use a `Termination` trait for the `main()` exit code and specify
      a minimum Rust version of 1.61

### Additions

- Add an EditorConfig definitions file.
- Python implementation:
    - declare Python 3.10 and 3.11 as supported versions
- Rust implementation:
    - add the `run-clippy.sh` tool to run a lot of diagnostic checks
- Testing framework:
    - add Nix shell expressions for running the test suites for the Perl and
      Python implementations in a clean ("pure") Nix environment

### Other changes

- Rust implementation:
    - refactor a lot according to many suggestions from Clippy
    - bump the version of the `expect-exit` dependency to 0.5 for
      the `bool.or_exit()` implementation
    - use a Nom-based parser for the `featurename` and `featurename op version`
      expressions that may be specified on the command line
    - use a Nom-based parser for the output of the examined program
    - keep the `Cargo.lock` file under version control
    - use the `clap` library for command-line arguments parsing
- Python implementation:
    - use black 22 for source code formatting, reformat with 100 characters
      per line
    - move the configuration of more static checkers to the `pyproject.toml`
      file
    - use `pytest.mark.parametrize()` instead of `ddt` for simpler tests
    - use a pyparsing-based parser for the `featurename` and
      `featurename op version` expressions that may be specified on
      the command line
    - use a pyparsing-based parser for the output of the examined program
    - drop a `type: ignore` comment for a bug fixed in the `mypy` tool
    - fix the `python/3/feature-check.sh` wrapper so that it does the right
      thing if the `PYTHONPATH` environment variable is already set
- Testing framework:
    - be more permissive when looking for the program's usage message in
      the incorrect command-line options output
    - skip some of the program usage message tests for the Rust implementation,
      too, since the `clap` library can format the text in different ways

## [1.0.1] - 2021-12-17

### Additions

- Python implementation:
    - add tests for comparisons against beta versions of features
    - actually install the py.typed marker file via the declarative
      setuptools configuration
- Rust implementation:
    - code clean-up:
        - add the `html_root_url` doc attribute

### Other changes

- Use common test definitions for the various implementations,
  generated and kept in sync via the new fcheck-testdata internal tool.
- Python implementation:
    - code clean-up:
        - add a version to the dependency on the "hacking" Python library in
          the tox.ini test definitions to help out pip's resolver
        - use f-strings instead of str.format()
        - use black's default line length of 88 characters
- Rust implementation:
    - code clean-up:
        - honor clippy's "needless borrow" suggestions
        - drop an unused internal structure field
        - get the crate version string from the Cargo manifest, one less place
          to update when bumping the version
        - move the module-level docs after the copyright notices
    - declare compatibility with the Rust 2021 edition with no changes
    - use the quick-error crate instead of writing boilerplate code

## [1.0.0] - 2021-06-24

### Incompatible changes

- Python implementation:
    - drop Python 2.x support

### Fixes

- Perl implementation:
    - fix a 2 < 10 version int/string bug
    - fix a 3.0.beta2 < 3.0 version int/string bug

### Additions

- Add a Rust implementation.

### Other changes

- Python implementation:
    - rework as more idiomatic Python 3.x
    - switch to a declarative setuptools config
    - add a PEP 517 pyproject.toml definition
    - reformat the source code using black
    - push the source into a src/ subdirectory

## [0.2.2] - 2019-01-09

### Fixes

- Fix the Python command-line tool's use of the standard Python
  JSON module if simplejson is not installed.

### Other changes

- Remove two unnecessary "pass" statements since the functions
  have a doc-string that serves as a null body.

## [0.2.1] - 2018-11-23

### Other changes

- Build universal Python wheels.
- Do not require the Python typing module, only use it when it is
  available, e.g. during type checking tests.

## [0.2.0] - 2018-11-22

### Additions

- Reorganize the Python implementation:
    - add flake8 and pylint checks
    - add some simple unit tests
    - add type hints

### Other changes

- Reorganize the Python implementation:
    - break it into modules

## [0.1.1] - 2018-05-08

### Fixes

- Perl 5.10 does not understand the ellipsis unimplemented statement,
  so replace it with a die() statement with an internal error message

## [0.1.0] - 2018-04-22

### Started

- first public release

[Unreleased]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.3.2...master
[2.3.2]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.3.1...release%2F2.3.2
[2.3.1]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.3.0...release%2F2.3.1
[2.3.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.2.0...release%2F2.3.0
[2.2.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.1.0...release%2F2.2.0
[2.1.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F2.0.0...release%2F2.1.0
[2.0.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F1.0.1...release%2F2.0.0
[1.0.1]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F1.0.0...release%2F1.0.1
[1.0.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F0.2.2...release%2F1.0.0
[0.2.2]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F0.2.1...release%2F0.2.2
[0.2.1]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F0.2.0...release%2F0.2.1
[0.2.0]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F0.1.1...release%2F0.2.0
[0.1.1]: https://gitlab.com/ppentchev/feature-check/-/compare/release%2F0.1.0...release%2F0.1.1
[0.1.0]: https://gitlab.com/ppentchev/feature-check/-/tags/release%2F0.1.0
