Skip to content

Commit

Permalink
feat: Separate FUTURE flags detection in check-future-flags command
Browse files Browse the repository at this point in the history
The `check-fixmes` command used to report both FIXME and orphan FUTURE
flags. In the future, all commands will have a `--format` argument
that allows text, CSV or JSON output. Reporting FIXME's and FUTURE
tags in a single CSV file seems hard, because they don't have the same
attributes.

As such, `check-fixmes` now only reports FIXME's. A separate command
`check-future-flags` command reports FUTURE flags. One tool, one job.
  • Loading branch information
dbaty committed Apr 12, 2024
1 parent f083978 commit ea892e1
Show file tree
Hide file tree
Showing 13 changed files with 407 additions and 169 deletions.
8 changes: 5 additions & 3 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
0.8.11 (unreleased)
-------------------
1.0.0 (unreleased)
------------------

- Nothing changed yet.
- |backward-incompatible| A new **check-future-tags** command is
introduced that reports orphan future tags. **check-fixmes** does
**not** report those tags anymore, it only reports outdated FIXME's.


0.8.10 (2023-08-16)
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ quality:
pylint --reports=no setup.py src/check_oldies tests
check-branches
check-fixmes
check-future-tags
python setup.py sdist >/dev/null 2>&1 && twine check dist/*

.PHONY: clean
Expand Down
103 changes: 14 additions & 89 deletions docs/check_fixmes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@ check-fixmes
Features and usage
==================

There are two main features:
This command detects old annotations: FIXME, TODO, etc.

- detection of old annotations (FIXME, TODO, etc.);
- detection of forgotten FUTURE tags.


Detection of old annotations
----------------------------

Rationale and principles
........................
------------------------

Developers use annotations to indicate that some code is deficient:
FIXME, TODO, OPTIMIZE, HACK, BUG, etc. Semantics vary, but the overall
Expand Down Expand Up @@ -46,7 +40,7 @@ used.


Usage and possible customization
................................
--------------------------------

.. code-block:: console
Expand Down Expand Up @@ -96,64 +90,19 @@ be an annotation, but not in this context. For example, in a CSS file:
}
If you need to ignore whole files, see the :ref:`whitelist option
<conf_whitelist>`.
<check_fixmes_conf_whitelist>`.

Possible customizations:

- which type of annotations are taken in account (FIXME, TODO,
OPTIMIZE, etc.): see the :ref:`annotations option
<conf_annotations>`;
<check_fixmes_conf_annotations>`;

- how assignments are formatted: see the the :ref:`assignee_regex
option <conf_assignee_regex>`;
option <check_fixmes_conf_assignee_regex>`;

- the age above which an annotation is considered old: see the
:ref:`max-age option <conf_max_age>`;

See the :ref:`check_fixmes_configuration` section below for full details.


Detection of orphan FUTURE tags
-------------------------------

Rationale and principles
........................

Developers sometimes plan a broad modification that will span multiple
files. Instead of littering FIXME annotations everywhere, they can set
a single FIXME annotation and a FUTURE-xxx tag on the same line. Then,
wherever we need to make a modification, we only mention this
FUTURE-xxx tag without any FIXME. If we have to "postpone" a FIXME,
there is only line to touch.

Example:

.. code-block:: text
# in file1.py:
#
# FIXME (jsmith, FUTURE-SWITCH-TO-V2): remove this field when we switch to v2
#
# in file2.py:
#
# FUTURE-SWITCH-TO-V2: deprecate usage when we switch to v2
If we ever remove the FIXME but keep the FUTURE-SWITCH-TO-V2 tag in
``file2.py``, it is a mistake and **check-fixmes** warns us.


Usage and possible customization
................................

**check-fixmes** looks for tags that start with ``FUTURE-``
(e.g. ``FUTURE-SWITCH-TO-V2``) to make sure that at least one of them
appears on the same line as an annotation. If not, it is considered an
orphan tag and is reported as an error.

As for annotations, you can ignore a line by using
``no-check-fixmes``, and ignore whole files with the :ref:`whitelist
option <conf_whitelist>`. You can configure how tags are detected with
the :ref:`future_tag_regex option <conf_future_tag_regex>`.
:ref:`max-age option <check_fixmes_conf_max_age>`;

See the :ref:`check_fixmes_configuration` section below for full details.

Expand Down Expand Up @@ -195,7 +144,7 @@ configuration file:
Input options
-------------

.. _conf_path:
.. _check_fixmes_conf_path:

``path`` (overridable via the command line)
...........................................
Expand All @@ -208,7 +157,7 @@ annotations (recursively). It must be a Git checkout repository.
| Example: ``path = "src"``.

.. _conf_whitelist:
.. _check_fixmes_conf_whitelist:

``whitelist``
.............
Expand All @@ -224,7 +173,7 @@ whitelist whole files by providing a list of glob patterns.
Output options
--------------

.. _conf_colorize_errors:
.. _check_fixmes_conf_colorize_errors:

``colorize-errors``
...................
Expand All @@ -238,7 +187,7 @@ default foreground color.
| Example: ``colorize-errors = false``.

.. _conf_xunit_file:
.. _check_fixmes_conf_xunit_file:

``xunit-file`` (overridable via the command line)
.................................................
Expand All @@ -255,7 +204,7 @@ exist.
Detection options
-----------------

.. _conf_annotations:
.. _check_fixmes_conf_annotations:

``annotations``
...............
Expand All @@ -269,7 +218,7 @@ case insensitive: by default, both "todo", "TODO", "fixme" and
| Example: ``annotations = ["todo", "optimize", "fixme", "hack"]``.

.. _conf_assignee_regex:
.. _check_fixmes_conf_assignee_regex:

``assignee-regex``
..................
Expand All @@ -290,31 +239,7 @@ assignee in an annotation. Requirements:
.. _Python syntax: https://docs.python.org/3/library/re.html#regular-expression-syntax


.. _conf_future_tag_regex:

``future-tag-regex``
....................

The extended regular expression to use to detect FUTURE tags.

| Type: string (an extended regular expression).
| Default: ``"FUTURE-[-[:alnum:]\._]+?"``.
| Example: ``future-tag-regex = "HEREAFTER-[-[:alnum:]\._]+?"``.
.. _conf_ignored_orphans_annotations:

``ignored_orphans_annotations``
...............................

The list of annotations which will not trigger orphan FUTURE tags checks.
Note that **check-fixmes** is case insensitive:
by default, both "wontfix", "WONTFIX" will be ignored.

| Type: list.
| Default: ``["wontfix", "xxx"]`` (case insensitive).
| Example: ``ignored_annotations = ["wontfix", "nofix"]``.
.. _conf_max_age:
.. _check_fixmes_conf_max_age:

``max-age`` (overridable via the command line)
..............................................
Expand Down
186 changes: 186 additions & 0 deletions docs/check_future_tags.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
=================
check-future-tags
=================

Features and usage
==================

This command detects orphan "FUTURE" tags.


Rationale and principles
------------------------

Developers sometimes plan broad modifications that will span multiple
files. Instead of littering FIXME annotations everywhere, they can set
a single FIXME annotation and a FUTURE-xxx tag on the same line. Then,
wherever we need to make a modification, we only mention this
FUTURE-xxx tag without any FIXME. If we have to "postpone" a FIXME,
there is only line to touch.

Example:

.. code-block:: text
# in file1.py:
#
# FIXME (jsmith, FUTURE-SWITCH-TO-V2): remove this field when we switch to v2
#
# in file2.py:
#
# FUTURE-SWITCH-TO-V2: deprecate usage when we switch to v2
If we ever remove the FIXME but keep the FUTURE-SWITCH-TO-V2 tag in
``file2.py``, it is a mistake and **check-future-tags** warns us.


Usage and possible customization
--------------------------------

**check-future-tags** looks for tags that start with ``FUTURE-``
(e.g. ``FUTURE-SWITCH-TO-V2``) to make sure that at least one of them
appears on the same line as an annotation. If not, it is considered an
orphan tag and is reported as an error.

As for annotations, you can ignore a line by using
``no-check-fixmes``, and ignore whole files with the :ref:`whitelist
option <check_future_tags_conf_whitelist>`. You can configure how tags are detected with
the :ref:`future_tag_regex option <check_future_tags_conf_future_tag_regex>`.

See the :ref:`check_future_tags_configuration` section below for full details.


.. _check_future_tags_configuration:

Configuration
=============

**check-future-tags** takes its configuration from a TOML file. By
default and if present, ``pyproject.toml`` is read (as a courtesy for
Python projects, even though **check-future-tags** is
language-agnostic). A limited list of options can be overridden via
command line arguments (that you can list with ``check-future-tags
--help``). Such overrides take precedence over the values defined in
the configuration files (or the default values if omitted).

The TOML configuration file should have a ``[tool.check-future-tags]``
section, like this:

.. code-block:: toml
[tool.check-future-tags]
path = "src"
max-age = 30
For an example configuration file, see `the configuration file
<https://github.com/Polyconseil/check-oldies/blob/master/pyproject.toml#L1-L14>`_
of the **check-future-tags** project itself.

Here is the list of all options that can be configured via the TOML
configuration file:

.. contents::
:local:
:depth: 2


Input options
-------------

.. _check_future_tags_conf_path:

``path`` (overridable via the command line)
...........................................

The path of the directory in which **check-future-tags** looks for
annotations (recursively). It must be a Git checkout repository.

| Type: string.
| Default: ``"."`` (current working directory).
| Example: ``path = "src"``.

.. _check_future_tags_conf_whitelist:

``whitelist``
.............

If the ``no-check-fixmes`` pragma is not appropriate, you may
whitelist whole files by providing a list of glob patterns.

| Type: list.
| Default: ``[]`` (no whitelist).
| Example: ``whitelist = ["docs/*"]``.

Output options
--------------

.. _check_future_tags_conf_colorize_errors:

``colorize-errors``
...................

By default, errors (old annotations and orphan FUTURE tags) appear
in red. Set this option to ``false`` if you want to use the
default foreground color.

| Type: boolean.
| Default: ``true``.
| Example: ``colorize-errors = false``.

.. _check_future_tags_conf_xunit_file:

``xunit-file`` (overridable via the command line)
.................................................

The path to the xUnit report file to generate. **check-future-tags**
gracefully creates parent directories of the file if they do not
exist.

| Type: string (a path).
| Default: none (no xUnit file is generated).
| Example: ``xunit-file = "reports/xunit.xml"``.

Detection options
-----------------

.. _check_future_tags_conf_annotations:

``annotations``
...............

The list of annotations to look for. Note that **check-future-tags** is
case insensitive: by default, both "todo", "TODO", "fixme" and
"FIXME" will be reported.

| Type: list.
| Default: ``["fixme", "todo"]`` (case insensitive).
| Example: ``annotations = ["todo", "optimize", "fixme", "hack"]``.

.. _check_future_tags_conf_future_tag_regex:

``future-tag-regex``
....................

The extended regular expression to use to detect FUTURE tags.

| Type: string (an extended regular expression).
| Default: ``"FUTURE-[-[:alnum:]\._]+?"``.
| Example: ``future-tag-regex = "HEREAFTER-[-[:alnum:]\._]+?"``.
.. _check_future_tags_conf_ignored_orphans_annotations:

``ignored_orphans_annotations``
...............................

The list of annotations which will not trigger orphan FUTURE tags
checks. Note that **check-future-tags** is case insensitive: by
default, both "wontfix", "WONTFIX" will be ignored.

| Type: list.
| Default: ``["wontfix", "xxx"]`` (case insensitive).
| Example: ``ignored_orphans_annotations = ["wontfix", "nofix"]``.
Loading

0 comments on commit ea892e1

Please sign in to comment.