wexample-filestate-python 6.4.6__tar.gz → 6.7.0__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.
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/PKG-INFO +163 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/README.md +161 -2
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/pyproject.toml +2 -2
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/add_return_types_option.py +8 -7
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/fix_attrs_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/fix_blank_lines_option.py +4 -4
- wexample_filestate_python-6.7.0/src/wexample_filestate_python/option/python/format_option.py +53 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_class_attributes_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_class_docstring_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_class_methods_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_constants_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_main_guard_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_module_docstring_option.py +4 -2
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_module_functions_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_module_metadata_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_type_checking_block_option.py +4 -4
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/relocate_imports_option.py +4 -2
- wexample_filestate_python-6.7.0/src/wexample_filestate_python/option/python/remove_unused_option.py +38 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/unquote_annotations_option.py +5 -2
- wexample_filestate_python-6.7.0/src/wexample_filestate_python/utils/cst_cache.py +37 -0
- wexample_filestate_python-6.4.6/src/wexample_filestate_python/option/python/format_option.py +0 -34
- wexample_filestate_python-6.4.6/src/wexample_filestate_python/option/python/remove_unused_option.py +0 -45
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/common/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/common/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/common/pipy_gateway.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_option/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_option/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_option/mixin/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_option/mixin/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_option/mixin/with_stdout_wrapping_mixin.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_value/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_value/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/config_value/python_config_value.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/const/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/const/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/const/name_pattern.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/const/path.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/const/python_file.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/event/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/event/src/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/event/src/wexample_event/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/file/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/file/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/file/python_file.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/helpers/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/helpers/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/helpers/package.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/helpers/python/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/helpers/toml.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/abstract_python_file_content_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/add_future_annotations_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/class_name_matches_file_name_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/fstringify_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/modernize_typing_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/order_iterable_items_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python/sort_imports_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/option/python_option.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/options_provider/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/options_provider/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/options_provider/python_options_provider.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/py.typed +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_attrs_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_blank_lines_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_class_attributes_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_class_docstring_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_class_methods_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_constants_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_docstring_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_functions_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_iterable_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_main_guard_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_module_metadata_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/python_type_checking_utils.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/python_import_rewriter.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/python_localize_runtime_imports.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/python_parser_import_index.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/python_runtime_symbol_collector.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/src/wexample_filestate_python/utils/relocate_imports/python_usage_collector.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/tests/tests/__init__.py +0 -0
- {wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/tests/wexample_tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: wexample-filestate-python
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.7.0
|
|
4
4
|
Summary: Helpers for Python.
|
|
5
5
|
Author-Email: weeger <contact@wexample.com>
|
|
6
6
|
License: MIT
|
|
@@ -20,7 +20,7 @@ Requires-Dist: packaging
|
|
|
20
20
|
Requires-Dist: pyupgrade
|
|
21
21
|
Requires-Dist: tomli
|
|
22
22
|
Requires-Dist: wexample-api>=6.1.0
|
|
23
|
-
Requires-Dist: wexample-filestate>=
|
|
23
|
+
Requires-Dist: wexample-filestate>=11.1.0
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: pytest; extra == "dev"
|
|
26
26
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -28,7 +28,7 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
|
|
29
29
|
# filestate_python
|
|
30
30
|
|
|
31
|
-
Version: 6.
|
|
31
|
+
Version: 6.7.0
|
|
32
32
|
|
|
33
33
|
Helpers for Python.
|
|
34
34
|
|
|
@@ -119,7 +119,136 @@ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the comp
|
|
|
119
119
|
- pyupgrade:
|
|
120
120
|
- tomli:
|
|
121
121
|
- wexample-api: >=6.1.0
|
|
122
|
-
- wexample-filestate: >=
|
|
122
|
+
- wexample-filestate: >=11.1.0
|
|
123
|
+
|
|
124
|
+
## Versioning & Compatibility Policy
|
|
125
|
+
|
|
126
|
+
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
127
|
+
|
|
128
|
+
- **MAJOR**: Breaking changes
|
|
129
|
+
- **MINOR**: New features, backward compatible
|
|
130
|
+
- **PATCH**: Bug fixes, backward compatible
|
|
131
|
+
|
|
132
|
+
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
137
|
+
|
|
138
|
+
Free to use in both personal and commercial projects.
|
|
139
|
+
|
|
140
|
+
## Integration in the Suite
|
|
141
|
+
|
|
142
|
+
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.
|
|
143
|
+
|
|
144
|
+
### Related Packages
|
|
145
|
+
|
|
146
|
+
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.
|
|
147
|
+
|
|
148
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
149
|
+
|
|
150
|
+
# About us
|
|
151
|
+
|
|
152
|
+
[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.
|
|
153
|
+
|
|
154
|
+
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.
|
|
155
|
+
|
|
156
|
+
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.
|
|
157
|
+
|
|
158
|
+
# filestate_python
|
|
159
|
+
|
|
160
|
+
Version: 6.5.0
|
|
161
|
+
|
|
162
|
+
Helpers for Python.
|
|
163
|
+
|
|
164
|
+
## Table of Contents
|
|
165
|
+
|
|
166
|
+
- [Tests](#tests)
|
|
167
|
+
- [Suite Integration](#suite-integration)
|
|
168
|
+
- [Dependencies](#dependencies)
|
|
169
|
+
- [Versioning](#versioning)
|
|
170
|
+
- [License](#license)
|
|
171
|
+
- [Suite Integration](#suite-integration)
|
|
172
|
+
- [Suite Signature](#suite-signature)
|
|
173
|
+
- [Introduction](#introduction)
|
|
174
|
+
- [Roadmap](#roadmap)
|
|
175
|
+
- [Status Compatibility](#status-compatibility)
|
|
176
|
+
- [Useful Links](#useful-links)
|
|
177
|
+
- [Migration Notes](#migration-notes)
|
|
178
|
+
|
|
179
|
+
## Tests
|
|
180
|
+
|
|
181
|
+
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
182
|
+
|
|
183
|
+
### Installation
|
|
184
|
+
|
|
185
|
+
First, install the required testing dependencies:
|
|
186
|
+
```bash
|
|
187
|
+
.venv/bin/python -m pip install pytest pytest-cov
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Basic Usage
|
|
191
|
+
|
|
192
|
+
Run all tests with coverage:
|
|
193
|
+
```bash
|
|
194
|
+
.venv/bin/python -m pytest --cov --cov-report=html
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Common Commands
|
|
198
|
+
```bash
|
|
199
|
+
# Run tests with coverage for a specific module
|
|
200
|
+
.venv/bin/python -m pytest --cov=your_module
|
|
201
|
+
|
|
202
|
+
# Show which lines are not covered
|
|
203
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
204
|
+
|
|
205
|
+
# Generate an HTML coverage report
|
|
206
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
207
|
+
|
|
208
|
+
# Combine terminal and HTML reports
|
|
209
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
210
|
+
|
|
211
|
+
# Run specific test file with coverage
|
|
212
|
+
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Viewing HTML Reports
|
|
216
|
+
|
|
217
|
+
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
218
|
+
|
|
219
|
+
### Coverage Threshold
|
|
220
|
+
|
|
221
|
+
To enforce a minimum coverage percentage:
|
|
222
|
+
```bash
|
|
223
|
+
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This will cause the test suite to fail if coverage drops below 80%.
|
|
227
|
+
|
|
228
|
+
## Integration in the Suite
|
|
229
|
+
|
|
230
|
+
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.
|
|
231
|
+
|
|
232
|
+
### Related Packages
|
|
233
|
+
|
|
234
|
+
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.
|
|
235
|
+
|
|
236
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
237
|
+
|
|
238
|
+
## Dependencies
|
|
239
|
+
|
|
240
|
+
- attrs: >=23.1.0
|
|
241
|
+
- autoflake:
|
|
242
|
+
- black:
|
|
243
|
+
- cattrs: >=23.1.0
|
|
244
|
+
- flynt:
|
|
245
|
+
- isort:
|
|
246
|
+
- libcst:
|
|
247
|
+
- packaging:
|
|
248
|
+
- pyupgrade:
|
|
249
|
+
- tomli:
|
|
250
|
+
- wexample-api: >=6.1.0
|
|
251
|
+
- wexample-filestate: >=9.0.0
|
|
123
252
|
|
|
124
253
|
## Versioning & Compatibility Policy
|
|
125
254
|
|
|
@@ -342,3 +471,33 @@ See the [project roadmap](https://github.com/wexample/python-filestate_python/is
|
|
|
342
471
|
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
343
472
|
|
|
344
473
|
Breaking changes are clearly documented with upgrade paths and examples.
|
|
474
|
+
|
|
475
|
+
## Known Limitations & Roadmap
|
|
476
|
+
|
|
477
|
+
Current limitations and planned features are tracked in the GitHub issues.
|
|
478
|
+
|
|
479
|
+
See the [project roadmap](https://github.com/wexample/python-filestate_python/issues) for upcoming features and improvements.
|
|
480
|
+
|
|
481
|
+
## Status & Compatibility
|
|
482
|
+
|
|
483
|
+
**Maturity**: Production-ready
|
|
484
|
+
|
|
485
|
+
**Python Support**: >=3.10
|
|
486
|
+
|
|
487
|
+
**OS Support**: Linux, macOS, Windows
|
|
488
|
+
|
|
489
|
+
**Status**: Actively maintained
|
|
490
|
+
|
|
491
|
+
## Useful Links
|
|
492
|
+
|
|
493
|
+
- **Homepage**: https://github.com/wexample/python-filestate-python
|
|
494
|
+
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
495
|
+
- **Issue Tracker**: https://github.com/wexample/python-filestate-python/issues
|
|
496
|
+
- **Discussions**: https://github.com/wexample/python-filestate-python/discussions
|
|
497
|
+
- **PyPI**: [pypi.org/project/filestate_python](https://pypi.org/project/filestate_python/)
|
|
498
|
+
|
|
499
|
+
## Migration Notes
|
|
500
|
+
|
|
501
|
+
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
502
|
+
|
|
503
|
+
Breaking changes are clearly documented with upgrade paths and examples.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# filestate_python
|
|
2
2
|
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.7.0
|
|
4
4
|
|
|
5
5
|
Helpers for Python.
|
|
6
6
|
|
|
@@ -91,7 +91,136 @@ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the comp
|
|
|
91
91
|
- pyupgrade:
|
|
92
92
|
- tomli:
|
|
93
93
|
- wexample-api: >=6.1.0
|
|
94
|
-
- wexample-filestate: >=
|
|
94
|
+
- wexample-filestate: >=11.1.0
|
|
95
|
+
|
|
96
|
+
## Versioning & Compatibility Policy
|
|
97
|
+
|
|
98
|
+
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
99
|
+
|
|
100
|
+
- **MAJOR**: Breaking changes
|
|
101
|
+
- **MINOR**: New features, backward compatible
|
|
102
|
+
- **PATCH**: Bug fixes, backward compatible
|
|
103
|
+
|
|
104
|
+
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
109
|
+
|
|
110
|
+
Free to use in both personal and commercial projects.
|
|
111
|
+
|
|
112
|
+
## Integration in the Suite
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
### Related Packages
|
|
117
|
+
|
|
118
|
+
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.
|
|
119
|
+
|
|
120
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
121
|
+
|
|
122
|
+
# About us
|
|
123
|
+
|
|
124
|
+
[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.
|
|
125
|
+
|
|
126
|
+
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.
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
# filestate_python
|
|
131
|
+
|
|
132
|
+
Version: 6.5.0
|
|
133
|
+
|
|
134
|
+
Helpers for Python.
|
|
135
|
+
|
|
136
|
+
## Table of Contents
|
|
137
|
+
|
|
138
|
+
- [Tests](#tests)
|
|
139
|
+
- [Suite Integration](#suite-integration)
|
|
140
|
+
- [Dependencies](#dependencies)
|
|
141
|
+
- [Versioning](#versioning)
|
|
142
|
+
- [License](#license)
|
|
143
|
+
- [Suite Integration](#suite-integration)
|
|
144
|
+
- [Suite Signature](#suite-signature)
|
|
145
|
+
- [Introduction](#introduction)
|
|
146
|
+
- [Roadmap](#roadmap)
|
|
147
|
+
- [Status Compatibility](#status-compatibility)
|
|
148
|
+
- [Useful Links](#useful-links)
|
|
149
|
+
- [Migration Notes](#migration-notes)
|
|
150
|
+
|
|
151
|
+
## Tests
|
|
152
|
+
|
|
153
|
+
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
154
|
+
|
|
155
|
+
### Installation
|
|
156
|
+
|
|
157
|
+
First, install the required testing dependencies:
|
|
158
|
+
```bash
|
|
159
|
+
.venv/bin/python -m pip install pytest pytest-cov
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Basic Usage
|
|
163
|
+
|
|
164
|
+
Run all tests with coverage:
|
|
165
|
+
```bash
|
|
166
|
+
.venv/bin/python -m pytest --cov --cov-report=html
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Common Commands
|
|
170
|
+
```bash
|
|
171
|
+
# Run tests with coverage for a specific module
|
|
172
|
+
.venv/bin/python -m pytest --cov=your_module
|
|
173
|
+
|
|
174
|
+
# Show which lines are not covered
|
|
175
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
176
|
+
|
|
177
|
+
# Generate an HTML coverage report
|
|
178
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
179
|
+
|
|
180
|
+
# Combine terminal and HTML reports
|
|
181
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
182
|
+
|
|
183
|
+
# Run specific test file with coverage
|
|
184
|
+
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Viewing HTML Reports
|
|
188
|
+
|
|
189
|
+
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
190
|
+
|
|
191
|
+
### Coverage Threshold
|
|
192
|
+
|
|
193
|
+
To enforce a minimum coverage percentage:
|
|
194
|
+
```bash
|
|
195
|
+
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
This will cause the test suite to fail if coverage drops below 80%.
|
|
199
|
+
|
|
200
|
+
## Integration in the Suite
|
|
201
|
+
|
|
202
|
+
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.
|
|
203
|
+
|
|
204
|
+
### Related Packages
|
|
205
|
+
|
|
206
|
+
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.
|
|
207
|
+
|
|
208
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
209
|
+
|
|
210
|
+
## Dependencies
|
|
211
|
+
|
|
212
|
+
- attrs: >=23.1.0
|
|
213
|
+
- autoflake:
|
|
214
|
+
- black:
|
|
215
|
+
- cattrs: >=23.1.0
|
|
216
|
+
- flynt:
|
|
217
|
+
- isort:
|
|
218
|
+
- libcst:
|
|
219
|
+
- packaging:
|
|
220
|
+
- pyupgrade:
|
|
221
|
+
- tomli:
|
|
222
|
+
- wexample-api: >=6.1.0
|
|
223
|
+
- wexample-filestate: >=9.0.0
|
|
95
224
|
|
|
96
225
|
## Versioning & Compatibility Policy
|
|
97
226
|
|
|
@@ -314,3 +443,33 @@ See the [project roadmap](https://github.com/wexample/python-filestate_python/is
|
|
|
314
443
|
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
315
444
|
|
|
316
445
|
Breaking changes are clearly documented with upgrade paths and examples.
|
|
446
|
+
|
|
447
|
+
## Known Limitations & Roadmap
|
|
448
|
+
|
|
449
|
+
Current limitations and planned features are tracked in the GitHub issues.
|
|
450
|
+
|
|
451
|
+
See the [project roadmap](https://github.com/wexample/python-filestate_python/issues) for upcoming features and improvements.
|
|
452
|
+
|
|
453
|
+
## Status & Compatibility
|
|
454
|
+
|
|
455
|
+
**Maturity**: Production-ready
|
|
456
|
+
|
|
457
|
+
**Python Support**: >=3.10
|
|
458
|
+
|
|
459
|
+
**OS Support**: Linux, macOS, Windows
|
|
460
|
+
|
|
461
|
+
**Status**: Actively maintained
|
|
462
|
+
|
|
463
|
+
## Useful Links
|
|
464
|
+
|
|
465
|
+
- **Homepage**: https://github.com/wexample/python-filestate-python
|
|
466
|
+
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
467
|
+
- **Issue Tracker**: https://github.com/wexample/python-filestate-python/issues
|
|
468
|
+
- **Discussions**: https://github.com/wexample/python-filestate-python/discussions
|
|
469
|
+
- **PyPI**: [pypi.org/project/filestate_python](https://pypi.org/project/filestate_python/)
|
|
470
|
+
|
|
471
|
+
## Migration Notes
|
|
472
|
+
|
|
473
|
+
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
474
|
+
|
|
475
|
+
Breaking changes are clearly documented with upgrade paths and examples.
|
|
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "wexample-filestate-python"
|
|
9
|
-
version = "6.
|
|
9
|
+
version = "6.7.0"
|
|
10
10
|
description = "Helpers for Python."
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "weeger", email = "contact@wexample.com" },
|
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
|
29
29
|
"pyupgrade",
|
|
30
30
|
"tomli",
|
|
31
31
|
"wexample-api>=6.1.0",
|
|
32
|
-
"wexample-filestate>=
|
|
32
|
+
"wexample-filestate>=11.1.0",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[project.readme]
|
|
@@ -22,7 +22,14 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
22
22
|
statements in a function agree on one of these literal types."""
|
|
23
23
|
import libcst as cst
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
26
|
+
get_python_source_and_module,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
src, module = get_python_source_and_module(target)
|
|
31
|
+
except Exception:
|
|
32
|
+
return target.get_local_file().read()
|
|
26
33
|
|
|
27
34
|
# We implement type inference and rewriting using LibCST to ensure
|
|
28
35
|
# robust, formatting-preserving edits. We extend inference to:
|
|
@@ -251,12 +258,6 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
251
258
|
)
|
|
252
259
|
return updated_node
|
|
253
260
|
|
|
254
|
-
try:
|
|
255
|
-
module = cst.parse_module(src)
|
|
256
|
-
except Exception:
|
|
257
|
-
# If parsing fails for any reason, return the original source unchanged
|
|
258
|
-
return src
|
|
259
|
-
|
|
260
261
|
# Collect known simple type names from the module
|
|
261
262
|
ktc = _KnownTypesCollector()
|
|
262
263
|
module.visit(ktc)
|
|
@@ -24,14 +24,14 @@ class FixAttrsOption(AbstractPythonFileContentOption):
|
|
|
24
24
|
- Ensure @attrs.define always uses kw_only=True
|
|
25
25
|
- Ensure @attr.s always uses kw_only=True
|
|
26
26
|
"""
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
28
|
+
get_python_source_and_module,
|
|
29
|
+
)
|
|
29
30
|
from wexample_filestate_python.utils.python_attrs_utils import (
|
|
30
31
|
fix_attrs_kw_only,
|
|
31
32
|
)
|
|
32
33
|
|
|
33
|
-
src = target
|
|
34
|
-
module = cst.parse_module(src)
|
|
34
|
+
src, module = get_python_source_and_module(target)
|
|
35
35
|
|
|
36
36
|
modified = fix_attrs_kw_only(module)
|
|
37
37
|
return modified.code
|
|
@@ -34,14 +34,14 @@ class FixBlankLinesOption(AbstractPythonFileContentOption):
|
|
|
34
34
|
|
|
35
35
|
Note: Module-level spacing (between classes/functions/imports) is handled by Black.
|
|
36
36
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
38
|
+
get_python_source_and_module,
|
|
39
|
+
)
|
|
39
40
|
from wexample_filestate_python.utils.python_blank_lines_utils import (
|
|
40
41
|
fix_function_blank_lines,
|
|
41
42
|
)
|
|
42
43
|
|
|
43
|
-
src = target
|
|
44
|
-
module = cst.parse_module(src)
|
|
44
|
+
src, module = get_python_source_and_module(target)
|
|
45
45
|
|
|
46
46
|
modified = fix_function_blank_lines(module)
|
|
47
47
|
return modified.code
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
4
|
+
|
|
5
|
+
from wexample_filestate.option.mixin.with_batch_option_mixin import (
|
|
6
|
+
WithBatchOptionMixin,
|
|
7
|
+
)
|
|
8
|
+
from wexample_helpers.decorator.base_class import base_class
|
|
9
|
+
|
|
10
|
+
from .abstract_python_file_content_option import AbstractPythonFileContentOption
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@base_class
|
|
19
|
+
class FormatOption(WithBatchOptionMixin, AbstractPythonFileContentOption):
|
|
20
|
+
_line_length: ClassVar[int] = 88
|
|
21
|
+
|
|
22
|
+
def get_description(self) -> str:
|
|
23
|
+
return "Format the Python file content using Black."
|
|
24
|
+
|
|
25
|
+
def _apply_content_change(self, target: TargetFileOrDirectoryType) -> str:
|
|
26
|
+
cache = self._get_or_build_batch_cache(target)
|
|
27
|
+
path_key = str(target.get_path())
|
|
28
|
+
if path_key in cache:
|
|
29
|
+
return cache[path_key]
|
|
30
|
+
return target.read_text()
|
|
31
|
+
|
|
32
|
+
def _run_batch_on_paths(
|
|
33
|
+
self,
|
|
34
|
+
reference_target: TargetFileOrDirectoryType,
|
|
35
|
+
paths: list[Path],
|
|
36
|
+
) -> None:
|
|
37
|
+
# Black is loaded lazily here. Thread-safety: dry_run()/apply() always
|
|
38
|
+
# call _prepare_options() before parallel inspection, which runs this
|
|
39
|
+
# method in the main thread first — so by the time worker threads run,
|
|
40
|
+
# the module is fully loaded and there is no concurrent first-import
|
|
41
|
+
# race on its lazy attribute table.
|
|
42
|
+
import black
|
|
43
|
+
|
|
44
|
+
mode = black.Mode(line_length=self._line_length)
|
|
45
|
+
for path in paths:
|
|
46
|
+
src = path.read_text()
|
|
47
|
+
try:
|
|
48
|
+
formatted = black.format_file_contents(src, fast=False, mode=mode)
|
|
49
|
+
if formatted != src:
|
|
50
|
+
path.write_text(formatted)
|
|
51
|
+
except black.NothingChanged:
|
|
52
|
+
pass
|
|
53
|
+
return None
|
|
@@ -21,14 +21,14 @@ class OrderClassAttributesOption(AbstractPythonFileContentOption):
|
|
|
21
21
|
Special include __slots__, __match_args__, and inner class Config. Operates on
|
|
22
22
|
contiguous attribute blocks and preserves comments attached to each attribute.
|
|
23
23
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
25
|
+
get_python_source_and_module,
|
|
26
|
+
)
|
|
26
27
|
from wexample_filestate_python.utils.python_class_attributes_utils import (
|
|
27
28
|
ensure_order_class_attributes_in_module,
|
|
28
29
|
)
|
|
29
30
|
|
|
30
|
-
src = target
|
|
31
|
-
module = cst.parse_module(src)
|
|
31
|
+
src, module = get_python_source_and_module(target)
|
|
32
32
|
|
|
33
33
|
modified = ensure_order_class_attributes_in_module(module)
|
|
34
34
|
return modified.code
|
|
@@ -23,14 +23,14 @@ class OrderClassDocstringOption(AbstractPythonFileContentOption):
|
|
|
23
23
|
decorators and the class header). Normalizes to double quotes. Avoids
|
|
24
24
|
whitespace-only diffs when already correct.
|
|
25
25
|
"""
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
27
|
+
get_python_source_and_module,
|
|
28
|
+
)
|
|
28
29
|
from wexample_filestate_python.utils.python_class_docstring_utils import (
|
|
29
30
|
ensure_all_classes_docstring_first,
|
|
30
31
|
)
|
|
31
32
|
|
|
32
|
-
src = target
|
|
33
|
-
module = cst.parse_module(src)
|
|
33
|
+
src, module = get_python_source_and_module(target)
|
|
34
34
|
|
|
35
35
|
modified = ensure_all_classes_docstring_first(module)
|
|
36
36
|
return modified.code
|
|
@@ -24,14 +24,14 @@ class OrderClassMethodsOption(AbstractPythonFileContentOption):
|
|
|
24
24
|
- Properties grouped by base name (getter/setter/deleter together), groups A–Z
|
|
25
25
|
- Instance methods: public A–Z, then private/protected A–Z
|
|
26
26
|
"""
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
28
|
+
get_python_source_and_module,
|
|
29
|
+
)
|
|
29
30
|
from wexample_filestate_python.utils.python_class_methods_utils import (
|
|
30
31
|
ensure_order_class_methods_in_module,
|
|
31
32
|
)
|
|
32
33
|
|
|
33
|
-
src = target
|
|
34
|
-
module = cst.parse_module(src)
|
|
34
|
+
src, module = get_python_source_and_module(target)
|
|
35
35
|
|
|
36
36
|
modified = ensure_order_class_methods_in_module(module)
|
|
37
37
|
return modified.code
|
|
@@ -22,14 +22,14 @@ class OrderConstantsOption(AbstractPythonFileContentOption):
|
|
|
22
22
|
A block is a contiguous sequence of simple UPPER_CASE assignments (no blank line between).
|
|
23
23
|
Non-flagged constants and other contexts are ignored.
|
|
24
24
|
"""
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
26
|
+
get_python_source_and_module,
|
|
27
|
+
)
|
|
27
28
|
from wexample_filestate_python.utils.python_constants_utils import (
|
|
28
29
|
reorder_flagged_constants_everywhere,
|
|
29
30
|
)
|
|
30
31
|
|
|
31
|
-
src = target
|
|
32
|
-
module = cst.parse_module(src)
|
|
32
|
+
src, module = get_python_source_and_module(target)
|
|
33
33
|
|
|
34
34
|
modified = reorder_flagged_constants_everywhere(module, src)
|
|
35
35
|
return modified.code
|
|
@@ -21,16 +21,16 @@ class OrderMainGuardOption(AbstractPythonFileContentOption):
|
|
|
21
21
|
Moves any top-level main-guard blocks to be the last non-empty statement in the
|
|
22
22
|
module (before trailing blank lines), preserving content and spacing as much as possible.
|
|
23
23
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
25
|
+
get_python_source_and_module,
|
|
26
|
+
)
|
|
26
27
|
from wexample_filestate_python.utils.python_main_guard_utils import (
|
|
27
28
|
find_main_guard_blocks,
|
|
28
29
|
is_main_guard_at_end,
|
|
29
30
|
move_main_guard_to_end,
|
|
30
31
|
)
|
|
31
32
|
|
|
32
|
-
src = target
|
|
33
|
-
module = cst.parse_module(src)
|
|
33
|
+
src, module = get_python_source_and_module(target)
|
|
34
34
|
|
|
35
35
|
# No main guard present => nothing to do
|
|
36
36
|
if not find_main_guard_blocks(module):
|
|
@@ -23,14 +23,16 @@ class OrderModuleDocstringOption(AbstractPythonFileContentOption):
|
|
|
23
23
|
"""
|
|
24
24
|
import libcst as cst
|
|
25
25
|
|
|
26
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
27
|
+
get_python_source_and_module,
|
|
28
|
+
)
|
|
26
29
|
from wexample_filestate_python.utils.python_docstring_utils import (
|
|
27
30
|
find_module_docstring,
|
|
28
31
|
is_module_docstring_at_top,
|
|
29
32
|
move_docstring_to_top,
|
|
30
33
|
)
|
|
31
34
|
|
|
32
|
-
src = target
|
|
33
|
-
module = cst.parse_module(src)
|
|
35
|
+
src, module = get_python_source_and_module(target)
|
|
34
36
|
|
|
35
37
|
# Check if there's a docstring and if it needs to be moved
|
|
36
38
|
docstring_node, position = find_module_docstring(module)
|
|
@@ -21,15 +21,15 @@ class OrderModuleFunctionsOption(AbstractPythonFileContentOption):
|
|
|
21
21
|
- Keeps @overload groups attached to their implementation.
|
|
22
22
|
- Preserves spacing/comments by keeping each group's first function's leading_lines.
|
|
23
23
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
25
|
+
get_python_source_and_module,
|
|
26
|
+
)
|
|
26
27
|
from wexample_filestate_python.utils.python_functions_utils import (
|
|
27
28
|
module_functions_sorted_before_classes,
|
|
28
29
|
reorder_module_functions,
|
|
29
30
|
)
|
|
30
31
|
|
|
31
|
-
src = target
|
|
32
|
-
module = cst.parse_module(src)
|
|
32
|
+
src, module = get_python_source_and_module(target)
|
|
33
33
|
|
|
34
34
|
# Quick no-op detection: if there are no functions, or functions already sorted
|
|
35
35
|
# and placed before classes, the transformation may be a noop.
|
|
@@ -23,16 +23,16 @@ class OrderModuleMetadataOption(AbstractPythonFileContentOption):
|
|
|
23
23
|
|
|
24
24
|
Placement: after imports and `if TYPE_CHECKING:` blocks, before other module-level code.
|
|
25
25
|
"""
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
27
|
+
get_python_source_and_module,
|
|
28
|
+
)
|
|
28
29
|
from wexample_filestate_python.utils.python_module_metadata_utils import (
|
|
29
30
|
find_module_metadata_statements,
|
|
30
31
|
group_and_sort_module_metadata,
|
|
31
32
|
target_index_for_module_metadata,
|
|
32
33
|
)
|
|
33
34
|
|
|
34
|
-
src = target
|
|
35
|
-
module = cst.parse_module(src)
|
|
35
|
+
src, module = get_python_source_and_module(target)
|
|
36
36
|
|
|
37
37
|
found = find_module_metadata_statements(module)
|
|
38
38
|
if not found:
|
|
@@ -22,16 +22,16 @@ class OrderTypeCheckingBlockOption(AbstractPythonFileContentOption):
|
|
|
22
22
|
after the last regular import section (or after `from __future__ import ...`
|
|
23
23
|
if no regular imports exist). Keeps spacing minimal and preserves content.
|
|
24
24
|
"""
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
26
|
+
get_python_source_and_module,
|
|
27
|
+
)
|
|
27
28
|
from wexample_filestate_python.utils.python_type_checking_utils import (
|
|
28
29
|
find_type_checking_blocks,
|
|
29
30
|
move_type_checking_blocks_after_imports,
|
|
30
31
|
target_index_for_type_checking,
|
|
31
32
|
)
|
|
32
33
|
|
|
33
|
-
src = target
|
|
34
|
-
module = cst.parse_module(src)
|
|
34
|
+
src, module = get_python_source_and_module(target)
|
|
35
35
|
|
|
36
36
|
blocks = find_type_checking_blocks(module)
|
|
37
37
|
if not blocks:
|
|
@@ -35,6 +35,9 @@ class RelocateImportsOption(AbstractPythonFileContentOption):
|
|
|
35
35
|
|
|
36
36
|
import libcst as cst
|
|
37
37
|
|
|
38
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
39
|
+
get_python_source_and_module,
|
|
40
|
+
)
|
|
38
41
|
from wexample_filestate_python.utils.relocate_imports.python_import_rewriter import (
|
|
39
42
|
PythonImportRewriter,
|
|
40
43
|
)
|
|
@@ -51,8 +54,7 @@ class RelocateImportsOption(AbstractPythonFileContentOption):
|
|
|
51
54
|
PythonUsageCollector,
|
|
52
55
|
)
|
|
53
56
|
|
|
54
|
-
src = target
|
|
55
|
-
module = cst.parse_module(src)
|
|
57
|
+
src, module = get_python_source_and_module(target)
|
|
56
58
|
|
|
57
59
|
# Index current imports using shared utility
|
|
58
60
|
idx = PythonParserImportIndex()
|
wexample_filestate_python-6.7.0/src/wexample_filestate_python/option/python/remove_unused_option.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from wexample_helpers.decorator.base_class import base_class
|
|
6
|
+
|
|
7
|
+
from .abstract_python_file_content_option import AbstractPythonFileContentOption
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@base_class
|
|
14
|
+
class RemoveUnusedOption(AbstractPythonFileContentOption):
|
|
15
|
+
def get_description(self) -> str:
|
|
16
|
+
return "Remove unused imports from the Python file using autoflake."
|
|
17
|
+
|
|
18
|
+
def _apply_content_change(self, target: TargetFileOrDirectoryType) -> str:
|
|
19
|
+
"""Remove unused Python imports using autoflake's in-process API.
|
|
20
|
+
|
|
21
|
+
Previously shelled out to `autoflake --stdout` per file, costing ~80ms
|
|
22
|
+
of subprocess + Python startup overhead each call (≈20s on a 268-file
|
|
23
|
+
project).
|
|
24
|
+
"""
|
|
25
|
+
from autoflake import fix_code
|
|
26
|
+
|
|
27
|
+
src = target.get_local_file().read()
|
|
28
|
+
try:
|
|
29
|
+
return fix_code(
|
|
30
|
+
src,
|
|
31
|
+
remove_all_unused_imports=True,
|
|
32
|
+
remove_unused_variables=True,
|
|
33
|
+
expand_star_imports=True,
|
|
34
|
+
remove_duplicate_keys=True,
|
|
35
|
+
)
|
|
36
|
+
except Exception as e:
|
|
37
|
+
target.io.error(f"Autoflake error: {e}\n\n")
|
|
38
|
+
return src
|
|
@@ -21,7 +21,11 @@ class UnquoteAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
21
21
|
|
|
22
22
|
import libcst as cst
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
from wexample_filestate_python.utils.cst_cache import (
|
|
25
|
+
get_python_source_and_module,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
src, module = get_python_source_and_module(target)
|
|
25
29
|
|
|
26
30
|
class _Unquoter(cst.CSTTransformer):
|
|
27
31
|
@staticmethod
|
|
@@ -80,6 +84,5 @@ class UnquoteAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
80
84
|
return updated_node.with_changes(annotation=expr)
|
|
81
85
|
return updated_node
|
|
82
86
|
|
|
83
|
-
module = cst.parse_module(src)
|
|
84
87
|
new_mod = module.visit(_Unquoter())
|
|
85
88
|
return new_mod.code
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Per-target libcst parse cache.
|
|
2
|
+
|
|
3
|
+
Within a single rectification scan, a Python file's disk content does not
|
|
4
|
+
change — yet historically each option parsed the libcst module independently,
|
|
5
|
+
multiplying the parse cost by the number of content options (~15). This
|
|
6
|
+
helper caches the `(src, module)` pair on the target item so all options on
|
|
7
|
+
the same file share a single parse.
|
|
8
|
+
|
|
9
|
+
The cache is naturally invalidated between rectification passes (a new
|
|
10
|
+
workdir means new target instances).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
import libcst as cst
|
|
19
|
+
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
_CACHE_ATTR = "_cst_cache"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_python_source_and_module(
|
|
26
|
+
target: TargetFileOrDirectoryType,
|
|
27
|
+
) -> tuple[str, cst.Module]:
|
|
28
|
+
cached = getattr(target, _CACHE_ATTR, None)
|
|
29
|
+
if cached is not None:
|
|
30
|
+
return cached
|
|
31
|
+
|
|
32
|
+
import libcst as cst
|
|
33
|
+
|
|
34
|
+
src = target.get_local_file().read()
|
|
35
|
+
module = cst.parse_module(src)
|
|
36
|
+
setattr(target, _CACHE_ATTR, (src, module))
|
|
37
|
+
return src, module
|
wexample_filestate_python-6.4.6/src/wexample_filestate_python/option/python/format_option.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, ClassVar
|
|
4
|
-
|
|
5
|
-
from wexample_helpers.decorator.base_class import base_class
|
|
6
|
-
|
|
7
|
-
from .abstract_python_file_content_option import AbstractPythonFileContentOption
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@base_class
|
|
14
|
-
class FormatOption(AbstractPythonFileContentOption):
|
|
15
|
-
# Use ClassVar to avoid Pydantic treating it as a model field/private attr
|
|
16
|
-
_line_length: ClassVar[int] = 88
|
|
17
|
-
|
|
18
|
-
def get_description(self) -> str:
|
|
19
|
-
return "Format the Python file content using Black."
|
|
20
|
-
|
|
21
|
-
def _apply_content_change(self, target: TargetFileOrDirectoryType) -> str:
|
|
22
|
-
"""Format Python files using Black."""
|
|
23
|
-
import black
|
|
24
|
-
|
|
25
|
-
src = target.get_local_file().read()
|
|
26
|
-
mode = black.Mode(line_length=self._line_length)
|
|
27
|
-
|
|
28
|
-
try:
|
|
29
|
-
formatted = black.format_file_contents(src, fast=False, mode=mode)
|
|
30
|
-
return formatted
|
|
31
|
-
except black.NothingChanged:
|
|
32
|
-
return src
|
|
33
|
-
except Exception as e:
|
|
34
|
-
raise e
|
wexample_filestate_python-6.4.6/src/wexample_filestate_python/option/python/remove_unused_option.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from wexample_helpers.decorator.base_class import base_class
|
|
6
|
-
|
|
7
|
-
from .abstract_python_file_content_option import AbstractPythonFileContentOption
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@base_class
|
|
14
|
-
class RemoveUnusedOption(AbstractPythonFileContentOption):
|
|
15
|
-
def get_description(self) -> str:
|
|
16
|
-
return "Remove unused imports from the Python file using autoflake."
|
|
17
|
-
|
|
18
|
-
def _apply_content_change(self, target: TargetFileOrDirectoryType) -> str:
|
|
19
|
-
"""Remove unused Python imports using autoflake."""
|
|
20
|
-
from wexample_helpers.helpers.shell import shell_run
|
|
21
|
-
from wexample_helpers.helpers.system import system_get_venv_bin_path
|
|
22
|
-
|
|
23
|
-
result = shell_run(
|
|
24
|
-
cmd=[
|
|
25
|
-
f"{system_get_venv_bin_path()}/autoflake",
|
|
26
|
-
"--stdout",
|
|
27
|
-
"--remove-all-unused-imports",
|
|
28
|
-
"--remove-unused-variables",
|
|
29
|
-
"--expand-star-imports",
|
|
30
|
-
"--remove-duplicate-keys",
|
|
31
|
-
str(target.get_path()),
|
|
32
|
-
],
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
if result.returncode != 0:
|
|
36
|
-
# Double line return is important to keep message visible event last line is erased by parent process.
|
|
37
|
-
target.io.error(f"Autoflake error: {result.stderr}\n\n")
|
|
38
|
-
return target.get_local_file().read() # Return original content on error
|
|
39
|
-
|
|
40
|
-
modified_content = result.stdout
|
|
41
|
-
|
|
42
|
-
if not modified_content.strip():
|
|
43
|
-
return target.get_local_file().read() # Return original content if empty
|
|
44
|
-
|
|
45
|
-
return modified_content
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wexample_filestate_python-6.4.6 → wexample_filestate_python-6.7.0}/tests/wexample_tests/__init__.py
RENAMED
|
File without changes
|