commented-configparser 2.2.0__tar.gz → 3.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. commented_configparser-3.1.1/.github/workflows/pypi-publish.yml +62 -0
  2. commented_configparser-3.1.1/.github/workflows/python-tests.yml +116 -0
  3. commented_configparser-3.1.1/.python-version +1 -0
  4. commented_configparser-3.1.1/CONTRIBUTING.md +115 -0
  5. {commented_configparser-2.2.0/src/commented_configparser.egg-info → commented_configparser-3.1.1}/PKG-INFO +25 -36
  6. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/README.md +19 -18
  7. commented_configparser-3.1.1/noxfile.py +149 -0
  8. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/pyproject.toml +37 -22
  9. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/src/commentedconfigparser/commentedconfigparser.py +74 -23
  10. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/commentedconfigparser_test.py +10 -7
  11. commented_configparser-3.1.1/tests/empty_comments_expected.ini +17 -0
  12. commented_configparser-3.1.1/tests/empty_comments_input.ini +17 -0
  13. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/header_expected.ini +0 -1
  14. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/multi_expected.ini +0 -1
  15. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/pydocs_expected.ini +2 -2
  16. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/regression_original_expected.ini +3 -2
  17. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/regression_original_input.ini +1 -0
  18. commented_configparser-3.1.1/uv.lock +685 -0
  19. commented_configparser-2.2.0/.github/workflows/pypi-publish.yml +0 -56
  20. commented_configparser-2.2.0/.github/workflows/python-tests.yml +0 -119
  21. commented_configparser-2.2.0/.pre-commit-config.yaml +0 -32
  22. commented_configparser-2.2.0/CONTRIBUTING.md +0 -120
  23. commented_configparser-2.2.0/PKG-INFO +0 -138
  24. commented_configparser-2.2.0/noxfile.py +0 -203
  25. commented_configparser-2.2.0/requirements/constraints.txt +0 -38
  26. commented_configparser-2.2.0/requirements/requirements-dev.txt +0 -13
  27. commented_configparser-2.2.0/requirements/requirements-test.txt +0 -5
  28. commented_configparser-2.2.0/requirements/requirements.txt +0 -1
  29. commented_configparser-2.2.0/setup.cfg +0 -4
  30. commented_configparser-2.2.0/src/commented_configparser.egg-info/SOURCES.txt +0 -32
  31. commented_configparser-2.2.0/src/commented_configparser.egg-info/dependency_links.txt +0 -1
  32. commented_configparser-2.2.0/src/commented_configparser.egg-info/requires.txt +0 -13
  33. commented_configparser-2.2.0/src/commented_configparser.egg-info/top_level.txt +0 -1
  34. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/.flake8 +0 -0
  35. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/.gitignore +0 -0
  36. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/LICENSE +0 -0
  37. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/src/commentedconfigparser/__init__.py +0 -0
  38. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/src/commentedconfigparser/py.typed +0 -0
  39. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/header_input.ini +0 -0
  40. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/multi01_input.ini +0 -0
  41. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/multi02_input.ini +0 -0
  42. {commented_configparser-2.2.0 → commented_configparser-3.1.1}/tests/pydocs_input.ini +0 -0
@@ -0,0 +1,62 @@
1
+ name: "Publish Python distribution to PyPI"
2
+ # Uses:
3
+ # https://github.com/actions/checkout : v7.0.1 de0fac2e4500dabe0009e67214ff5f5447ce83dd
4
+ # https://github.com/actions/download-artifact : v8.0.2 9000827ccba6bdab643e8b6fd33ac0654aef8333
5
+ # https://github.com/actions/upload-artifact : v7.0.2 cf430e030ddbb5b0abf93d22962f4752f3646cd9
6
+ # https://github.com/astral-sh/setup-uv : v10.3.2 07a047e608db84b3d8c06cd9a7c7dcc9c355c18e
7
+ # https://github.com/pypa/gh-action-pypi-publish : v1.14.3 7245906fb61fa33a13554f9d5fb856fe61758086
8
+
9
+ on:
10
+ release:
11
+ types: [published]
12
+
13
+ jobs:
14
+ build:
15
+ name: "Build package"
16
+ runs-on: "ubuntu-latest"
17
+ outputs:
18
+ artifact-id: "${{ steps.upload-artifact.outputs.artifact-id }}"
19
+
20
+ steps:
21
+ - uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd"
22
+ with:
23
+ persist-credentials: false
24
+
25
+ - name: "Install the latest version of uv"
26
+ uses: "astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e"
27
+ with:
28
+ version: "latest"
29
+ enable-cache: true
30
+
31
+ - name: "Build the package"
32
+ run: "uvx nox --session build"
33
+
34
+ - name: "Store the distribution packages"
35
+ id: "upload-artifact"
36
+ uses: "actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9"
37
+ with:
38
+ path: "./dist"
39
+
40
+ publish-to-pypi:
41
+ name: "Publish Python Distribution to PyPI"
42
+ needs: ["build"]
43
+ runs-on: "ubuntu-latest"
44
+ environment:
45
+ name: "pypi"
46
+ url: "https://pypi.org/project/commented-configparser/"
47
+ permissions:
48
+ id-token: "write"
49
+
50
+ steps:
51
+ - name: "Download all the dists"
52
+ uses: "actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 "
53
+ with:
54
+ artifact-ids: "${{ needs.build.outputs.artifact-id }}"
55
+ path: "./dist"
56
+ merge-multiple: true
57
+
58
+ - name: "Publish distribution to PyPI"
59
+ uses: "pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086"
60
+ with:
61
+ repository-url: "https://upload.pypi.org/legacy/"
62
+ verbose: true
@@ -0,0 +1,116 @@
1
+ name: "python tests and coverage"
2
+ # Uses:
3
+ # https://github.com/actions/checkout : v7.0.1 de0fac2e4500dabe0009e67214ff5f5447ce83dd
4
+ # https://github.com/actions/download-artifact : v8.0.2 9000827ccba6bdab643e8b6fd33ac0654aef8333
5
+ # https://github.com/actions/upload-artifact : v7.0.2 cf430e030ddbb5b0abf93d22962f4752f3646cd9
6
+ # https://github.com/astral-sh/setup-uv : v10.3.2 07a047e608db84b3d8c06cd9a7c7dcc9c355c18e
7
+
8
+
9
+ on:
10
+ pull_request:
11
+ push:
12
+ branches:
13
+ - "main"
14
+
15
+ jobs:
16
+ set-statics:
17
+ name: "Set static values"
18
+ runs-on: "ubuntu-slim"
19
+ outputs:
20
+ linux-version: "ubuntu-26.04"
21
+ uv-version: "0.13.4"
22
+
23
+ steps:
24
+ - name: "Set Statics"
25
+ run: echo ""
26
+
27
+ run-tests-and-coverage:
28
+ name: "Run nox for tests and coverage"
29
+ needs: "set-statics"
30
+ runs-on: "${{ matrix.os }}"
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ os:
35
+ - "${{ needs.set-statics.outputs.linux-version }}"
36
+ - "windows-latest"
37
+ python-version:
38
+ - "3.11"
39
+ - "3.12"
40
+ - "3.13"
41
+ - "3.14"
42
+ - "3.15"
43
+
44
+ steps:
45
+ - name: "Repo checkout"
46
+ uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd"
47
+
48
+ - name: "Install the latest version of uv"
49
+ uses: "astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e"
50
+ with:
51
+ version: "${{ needs.set-statics.outputs.uv-version }}"
52
+ python-version: "${{ matrix.python-version }}"
53
+ enable-cache: true
54
+
55
+ - name: "Run tests and coverage via nox"
56
+ run: "uvx nox --session test -- partial-coverage"
57
+
58
+ - name: "Save coverage artifact"
59
+ uses: "actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9"
60
+ with:
61
+ name: "coverage-artifact-${{ matrix.os}}-${{ matrix.python-version}}"
62
+ path: ".coverage.*"
63
+ retention-days: 1
64
+ include-hidden-files: true
65
+
66
+ coverage-compile:
67
+ name: "coverage compile"
68
+ needs: ["set-statics", "run-tests-and-coverage"]
69
+ runs-on: "${{ needs.set-statics.outputs.linux-version }}"
70
+ steps:
71
+ - name: "Repo checkout"
72
+ uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd"
73
+
74
+ - name: "Install the latest version of uv"
75
+ uses: "astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e"
76
+ with:
77
+ version: "${{ needs.set-statics.outputs.uv-version }}"
78
+ enable-cache: true
79
+
80
+ - name: "Download coverage artifacts"
81
+ uses: "actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333"
82
+ with:
83
+ pattern: "coverage-artifact-*"
84
+ merge-multiple: true
85
+
86
+ - name: "Compile coverage data"
87
+ run: "uvx nox --session combine"
88
+
89
+ - name: "Post summary to step summary"
90
+ run: |
91
+ export TOTAL=$(python -c "import json;print(json.load(open('coverage.json'))['totals']['percent_covered_display'])")
92
+ echo "COVERAGE-TOTAL=$TOTAL" >> $GITHUB_ENV
93
+
94
+ linters-and-formatters:
95
+ name: "linters and formatters"
96
+ needs: "set-statics"
97
+ runs-on: "${{ needs.set-statics.outputs.linux-version }}"
98
+ steps:
99
+ - name: "Repo checkout"
100
+ uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd"
101
+
102
+ - name: "Install the latest version of uv"
103
+ uses: "astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e"
104
+ with:
105
+ version: "${{ needs.set-statics.outputs.uv-version }}"
106
+ enable-cache: true
107
+
108
+ - name: "Run linters and formatters"
109
+ run: "uvx nox --session format lint"
110
+
111
+ - name: "Check for any unstaged changes"
112
+ run: |
113
+ if [ -n "$(git status --porcelain)" ]; then
114
+ echo "#### Format or Lint changes found. Please run 'uvx nox' locally and push the changes." >> $GITHUB_STEP_SUMMARY
115
+ exit 1
116
+ fi
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,115 @@
1
+ # Contributing
2
+
3
+ Before contributing, please either ask to claim an existing open issue or create
4
+ a new issue to discuss your proposed changes with the owner(s) of this repo
5
+ before making any changes.
6
+
7
+ Any pull requests without a clearly defined issue being solved will be closed.
8
+
9
+ ### Bug reports
10
+
11
+ Found a bug but do not have time or do not wish to contribute a fix? Please
12
+ submit an issue for our awareness. Your feedback drives the continued
13
+ development of the project!
14
+
15
+ ### Pull Request
16
+
17
+ All pull requests must:
18
+
19
+ - Pass all linting and formatting checks
20
+ - Have tests that cover all branches of the added feature
21
+ - If the PR is a bug fix there must be a test that duplicates the bug, proving
22
+ it is fixed
23
+
24
+ ### Code Style
25
+
26
+ Follow the patterns seen in the code. Walk where others have walked.
27
+
28
+ Be sure to run the expected formatters and linters prior to opening the PR.
29
+
30
+ ### Tests
31
+
32
+ - Smaller tests are easier to work with
33
+ - Mock at a minimum
34
+ - No test should be dependent on another
35
+ - No test should be dependent on secrets/tokens
36
+
37
+ ---
38
+
39
+ # Local developer installation
40
+
41
+ The following steps outline how to install this repo for local development.
42
+
43
+ ## Prerequisites
44
+
45
+ ### [Install uv](https://docs.astral.sh/uv/getting-started/installation/)
46
+
47
+ uv is required to use the provided noxfile sessions for developer setup,
48
+ linting, and tests. Using nox is completely optional, all sessions can be
49
+ manually recreated. These instructions will not cover those cases.
50
+
51
+ ## Nox Sessions
52
+
53
+ ### Developer Install
54
+
55
+ ```console
56
+ uvx nox -s dev
57
+ ```
58
+
59
+ ### Validate uv.lock
60
+
61
+ ```console
62
+ uvx nox -s lock
63
+ ```
64
+
65
+ ### Run tests and display coverage
66
+
67
+ ```console
68
+ uvx nox -s test
69
+ ```
70
+
71
+ Passing extra arguements to pytest:
72
+
73
+ ```console
74
+ uvx nox -s test -- -vvv -x --full-trace
75
+ ```
76
+
77
+ ### Run linters
78
+
79
+ ```console
80
+ uvx nox -s lint
81
+ ```
82
+
83
+ ### Run formatters
84
+
85
+ ```console
86
+ uvx nox -s format
87
+ ```
88
+
89
+ ### Run all checks
90
+
91
+ ```console
92
+ uvx nox
93
+ ```
94
+
95
+ ### Build dist
96
+
97
+ ```console
98
+ uvx nox -s build
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Updating dependencies
104
+
105
+ Use the `uv` cli to add, update, and remove dependencies from the project.
106
+
107
+ ```console
108
+ uv add [package name]
109
+
110
+ uv remove [package name]
111
+
112
+ uv lock --upgrade
113
+
114
+ uv lock --upgrade-package [package name]
115
+ ```
@@ -1,46 +1,32 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: commented-configparser
3
- Version: 2.2.0
4
- Summary: Custom ConfigParser class that preserves comments in file when writing
3
+ Version: 3.1.1
4
+ Summary: A custom ConfigParser class that preserves comments and most formatting when writing loaded config out.
5
+ Project-URL: homepage, https://github.com/Preocts/commented-configparser
5
6
  Author-email: Preocts <preocts@preocts.com>
6
7
  License-Expression: MIT
7
- Project-URL: homepage, https://github.com/Preocts/commented-configparser
8
+ License-File: LICENSE
8
9
  Classifier: Programming Language :: Python :: 3
9
10
  Classifier: Programming Language :: Python :: 3 :: Only
10
11
  Classifier: Programming Language :: Python :: Implementation :: CPython
11
- Requires-Python: >=3.9
12
+ Requires-Python: >=3.11
12
13
  Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Provides-Extra: dev
15
- Requires-Dist: flake8; extra == "dev"
16
- Requires-Dist: flake8-builtins; extra == "dev"
17
- Requires-Dist: flake8-pep585; extra == "dev"
18
- Requires-Dist: black; extra == "dev"
19
- Requires-Dist: isort; extra == "dev"
20
- Requires-Dist: mypy; extra == "dev"
21
- Provides-Extra: test
22
- Requires-Dist: pytest; extra == "test"
23
- Requires-Dist: pytest-randomly; extra == "test"
24
- Requires-Dist: coverage; extra == "test"
25
- Dynamic: license-file
26
-
27
- [![Python 3.9 | 3.10 | 3.11 | 3.12 | 3.13 | 3.14](https://img.shields.io/badge/Python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://www.python.org/downloads)
28
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
29
- [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
30
14
 
31
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/Preocts/commented-configparser/main.svg)](https://results.pre-commit.ci/latest/github/Preocts/commented-configparser/main)
15
+ [![Python >=3.11](https://img.shields.io/badge/Python->=3.11-blue)](https://www.python.org/downloads)
16
+ [![PyPI - Version](https://img.shields.io/pypi/v/commented-configparser)](https://pypi.org/project/commented-configparser)
32
17
  [![Python tests](https://github.com/Preocts/commented-configparser/actions/workflows/python-tests.yml/badge.svg?branch=main)](https://github.com/Preocts/commented-configparser/actions/workflows/python-tests.yml)
33
18
 
34
- # commented-configparser
35
-
36
- - [Contributing Guide and Developer Setup Guide](./CONTRIBUTING.md)
37
- - [License: MIT](./LICENSE)
19
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
20
+ [![Nox](https://img.shields.io/badge/%F0%9F%A6%8A-Nox-D85E00.svg)](https://github.com/wntrblm/nox)
38
21
 
39
- ---
22
+ # commented-configparser
40
23
 
41
- A custom ConfigParser class that preserves comments and option casing when writing loaded config out.
24
+ A custom ConfigParser class that preserves comments and most formatting when
25
+ writing loaded config out.
42
26
 
43
- This library gives you a custom class of the standard library's `configparser.ConfigParger` which will preserve the comments of a loaded config file when writing that file back out.
27
+ This library gives you a custom class of the standard library's
28
+ `configparser.ConfigParger` which will preserve the comments of a loaded config
29
+ file when writing that file back out.
44
30
 
45
31
  ---
46
32
 
@@ -84,7 +70,11 @@ with open("myconfig.ini", "w") as savefile:
84
70
 
85
71
  ## Results
86
72
 
87
- We favor the line spacing choices of the `ConfigParser` class so the input format may not be preserved completely. However, the comments will be preserved.
73
+ There is the attempt to retain the original format. Known formats that will not
74
+ be preserved:
75
+
76
+ 1. Indents will not be preserved outside of multi-line values
77
+ 2. Spacing around assignments will be normalized.
88
78
 
89
79
  ### Before
90
80
 
@@ -103,13 +93,12 @@ logging=true
103
93
  ; and many could be between things
104
94
  [NEW SECTION]
105
95
  # Another comment
106
- multi-line=
96
+ multiLine=
107
97
  value01
108
98
  value02
109
99
  value03
110
100
  closing=0
111
101
  # Trailing comment
112
-
113
102
  ```
114
103
 
115
104
  ### After
@@ -123,16 +112,16 @@ foo = bar
123
112
  trace = false
124
113
  logging = true
125
114
  ; This is a comment as well
115
+
126
116
  # so we need to track all of them
127
- ; and many could be between things
128
117
 
118
+ ; and many could be between things
129
119
  [NEW SECTION]
130
120
  # Another comment
131
- multi-line =
121
+ multiLine =
132
122
  value01
133
123
  value02
134
124
  value03
135
125
  closing = 0
136
126
  # Trailing comment
137
-
138
127
  ```
@@ -1,20 +1,18 @@
1
- [![Python 3.9 | 3.10 | 3.11 | 3.12 | 3.13 | 3.14](https://img.shields.io/badge/Python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://www.python.org/downloads)
2
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
3
- [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
4
-
5
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/Preocts/commented-configparser/main.svg)](https://results.pre-commit.ci/latest/github/Preocts/commented-configparser/main)
1
+ [![Python >=3.11](https://img.shields.io/badge/Python->=3.11-blue)](https://www.python.org/downloads)
2
+ [![PyPI - Version](https://img.shields.io/pypi/v/commented-configparser)](https://pypi.org/project/commented-configparser)
6
3
  [![Python tests](https://github.com/Preocts/commented-configparser/actions/workflows/python-tests.yml/badge.svg?branch=main)](https://github.com/Preocts/commented-configparser/actions/workflows/python-tests.yml)
7
4
 
8
- # commented-configparser
9
-
10
- - [Contributing Guide and Developer Setup Guide](./CONTRIBUTING.md)
11
- - [License: MIT](./LICENSE)
5
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
6
+ [![Nox](https://img.shields.io/badge/%F0%9F%A6%8A-Nox-D85E00.svg)](https://github.com/wntrblm/nox)
12
7
 
13
- ---
8
+ # commented-configparser
14
9
 
15
- A custom ConfigParser class that preserves comments and option casing when writing loaded config out.
10
+ A custom ConfigParser class that preserves comments and most formatting when
11
+ writing loaded config out.
16
12
 
17
- This library gives you a custom class of the standard library's `configparser.ConfigParger` which will preserve the comments of a loaded config file when writing that file back out.
13
+ This library gives you a custom class of the standard library's
14
+ `configparser.ConfigParger` which will preserve the comments of a loaded config
15
+ file when writing that file back out.
18
16
 
19
17
  ---
20
18
 
@@ -58,7 +56,11 @@ with open("myconfig.ini", "w") as savefile:
58
56
 
59
57
  ## Results
60
58
 
61
- We favor the line spacing choices of the `ConfigParser` class so the input format may not be preserved completely. However, the comments will be preserved.
59
+ There is the attempt to retain the original format. Known formats that will not
60
+ be preserved:
61
+
62
+ 1. Indents will not be preserved outside of multi-line values
63
+ 2. Spacing around assignments will be normalized.
62
64
 
63
65
  ### Before
64
66
 
@@ -77,13 +79,12 @@ logging=true
77
79
  ; and many could be between things
78
80
  [NEW SECTION]
79
81
  # Another comment
80
- multi-line=
82
+ multiLine=
81
83
  value01
82
84
  value02
83
85
  value03
84
86
  closing=0
85
87
  # Trailing comment
86
-
87
88
  ```
88
89
 
89
90
  ### After
@@ -97,16 +98,16 @@ foo = bar
97
98
  trace = false
98
99
  logging = true
99
100
  ; This is a comment as well
101
+
100
102
  # so we need to track all of them
101
- ; and many could be between things
102
103
 
104
+ ; and many could be between things
103
105
  [NEW SECTION]
104
106
  # Another comment
105
- multi-line =
107
+ multiLine =
106
108
  value01
107
109
  value02
108
110
  value03
109
111
  closing = 0
110
112
  # Trailing comment
111
-
112
113
  ```
@@ -0,0 +1,149 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import functools
5
+ import pathlib
6
+ import shutil
7
+
8
+ import nox
9
+
10
+ # Control factors for finding pieces of the module
11
+ MODULE_NAME = "commentedconfigparser"
12
+ LINT_PATH = "./src"
13
+ TESTS_PATH = "./tests"
14
+
15
+ _file_python_version = pathlib.Path(".python-version").read_text()
16
+ _uv_python_version = os.getenv("UV_PYTHON", "")
17
+ # Favor the UV_PYTHON environment variable as this should override the .python-version
18
+ PYTHON_VERSION = _uv_python_version or _file_python_version
19
+
20
+ # What we allowed to clean (delete)
21
+ CLEANABLE_TARGETS = [
22
+ "./dist",
23
+ "./build",
24
+ "./.nox",
25
+ "./.coverage",
26
+ "./.coverage.*",
27
+ "./coverage.json",
28
+ "./htmlcov",
29
+ "./**/.mypy_cache",
30
+ "./**/.pytest_cache",
31
+ "./**/__pycache__",
32
+ "./**/*.pyc",
33
+ "./**/*.pyo",
34
+ ]
35
+
36
+ # Define the default sessions run when `nox` is called on the CLI
37
+ nox.options.default_venv_backend = "uv"
38
+ nox.options.sessions = ["lock", "format", "lint", "test"]
39
+
40
+ # All linters and formatters are run with `uv run --active`
41
+ LINTERS: list[tuple[str, ...]] = [
42
+ ("flake8", "--show-source", LINT_PATH, TESTS_PATH),
43
+ ("mypy", "--pretty", "--package", MODULE_NAME),
44
+ ("mypy", "--pretty", TESTS_PATH),
45
+ ]
46
+ FORMATTERS: list[tuple[str, ...]] = [
47
+ (
48
+ "isort",
49
+ "--force-single-line-imports",
50
+ "--profile",
51
+ "black",
52
+ "--add-import",
53
+ "from __future__ import annotations",
54
+ LINT_PATH,
55
+ TESTS_PATH,
56
+ ),
57
+ ("black", LINT_PATH, TESTS_PATH),
58
+ ]
59
+
60
+ # Default args for all 'uv sync' and 'uv run' calls
61
+ UV_ARGS = [
62
+ "--frozen",
63
+ "--quiet",
64
+ "--active",
65
+ ]
66
+
67
+
68
+ @nox.session(name="dev", python=False)
69
+ def create_dev_environment(session: nox.Session) -> None:
70
+ """Create a development environment."""
71
+ session.run_install("uv", "sync", "--frozen")
72
+
73
+
74
+ @nox.session(name="test", python=PYTHON_VERSION)
75
+ def run_tests_with_coverage(session: nox.Session) -> None:
76
+ """Run pytest in isolated environment, display coverage. Extra arguements passed to pytest."""
77
+ partial = "partial-coverage" in session.posargs
78
+
79
+ session.run_install("uv", "sync", *UV_ARGS)
80
+
81
+ coverage = functools.partial(session.run, "uv", "run", *UV_ARGS, "coverage")
82
+
83
+ coverage("erase")
84
+
85
+ if partial:
86
+ session.posargs.remove("partial-coverage")
87
+ coverage("run", "--parallel-mode", "--module", "pytest", *session.posargs)
88
+ else:
89
+ coverage("run", "--module", "pytest", *session.posargs)
90
+ coverage("report", "--show-missing")
91
+ coverage("html")
92
+
93
+
94
+ @nox.session(name="combine", python=PYTHON_VERSION)
95
+ def combine_coverage(session: nox.Session) -> None:
96
+ """Combine parallel-mode coverage files and produce reports."""
97
+ session.run_install("uv", "sync", *UV_ARGS)
98
+
99
+ coverage = functools.partial(session.run, "uv", "run", *UV_ARGS, "coverage")
100
+
101
+ coverage("combine")
102
+ coverage("report", "--show-missing")
103
+ coverage("html")
104
+ coverage("json")
105
+
106
+
107
+ @nox.session(name="lint", python=PYTHON_VERSION)
108
+ def run_linters(session: nox.Session) -> None:
109
+ """Run code linters, and type checking against all files."""
110
+ session.run_install("uv", "sync", "--group", "lint", *UV_ARGS)
111
+
112
+ for linter_args in LINTERS:
113
+ session.run("uv", "run", *UV_ARGS, *linter_args)
114
+
115
+
116
+ @nox.session(name="format", python=PYTHON_VERSION)
117
+ def run_formatters(session: nox.Session) -> None:
118
+ """Run code formatters against all files."""
119
+ session.run_install("uv", "sync", "--group", "format", *UV_ARGS)
120
+
121
+ for formatter_args in FORMATTERS:
122
+ session.run("uv", "run", *UV_ARGS, *formatter_args)
123
+
124
+
125
+ @nox.session(name="build", python=False)
126
+ def build_artifacts(session: nox.Session) -> None:
127
+ """Build a sdist and wheel."""
128
+ session.run("uv", "build")
129
+
130
+
131
+ @nox.session(name="lock", python=False)
132
+ def validate_lock_file(session: nox.Session) -> None:
133
+ """Ensure the uv.lock file exists and is aligned with dependencies."""
134
+ session.run("uv", "lock", "--check")
135
+
136
+
137
+ @nox.session(name="clean", python=False)
138
+ def clean_project_files(session: nox.Session) -> None:
139
+ """Clean cache, .pyc, .pyo, and build artifact files from project."""
140
+ count = 0
141
+ for searchpath in CLEANABLE_TARGETS:
142
+ for filepath in pathlib.Path(".").glob(searchpath):
143
+ if filepath.is_dir():
144
+ shutil.rmtree(filepath)
145
+ else:
146
+ filepath.unlink()
147
+ count += 1
148
+
149
+ session.log(f"{count} files cleaned.")