wexample-filestate-python 7.0.0__tar.gz → 8.0.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-7.0.0 → wexample_filestate_python-8.0.0}/PKG-INFO +6 -8
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/README.md +3 -4
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/pyproject.toml +3 -4
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_option/mixin/with_stdout_wrapping_mixin.py +5 -5
- wexample_filestate_python-8.0.0/src/wexample_filestate_python/config_value/python_config_value.py +210 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/file/python_file.py +1 -1
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/helpers/package.py +12 -24
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/helpers/toml.py +4 -3
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/add_future_annotations_option.py +10 -8
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/add_return_types_option.py +38 -36
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/class_name_matches_file_name_option.py +10 -9
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/fix_attrs_option.py +1 -1
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/fix_blank_lines_option.py +2 -3
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/format_option.py +4 -3
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/fstringify_option.py +1 -6
- wexample_filestate_python-8.0.0/src/wexample_filestate_python/option/python/modernize_typing_option.py +77 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_class_attributes_option.py +5 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_class_docstring_option.py +2 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_class_methods_option.py +5 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_constants_option.py +5 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_iterable_items_option.py +1 -2
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_main_guard_option.py +2 -6
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_module_docstring_option.py +2 -7
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_module_functions_option.py +6 -9
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_module_metadata_option.py +8 -12
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/order_type_checking_block_option.py +3 -3
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/relocate_imports_option.py +3 -4
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/remove_unused_option.py +7 -11
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/sort_imports_option.py +10 -4
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/unquote_annotations_option.py +12 -9
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python_option.py +4 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/options_provider/python_options_provider.py +3 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/cst_cache.py +3 -2
- wexample_filestate_python-8.0.0/src/wexample_filestate_python/utils/python_attrs_utils.py +95 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_blank_lines_utils.py +24 -81
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_class_attributes_utils.py +10 -10
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_class_docstring_utils.py +12 -14
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_class_methods_utils.py +61 -75
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_constants_utils.py +8 -11
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_docstring_utils.py +2 -7
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_functions_utils.py +73 -49
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_iterable_utils.py +47 -48
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_main_guard_utils.py +6 -8
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_module_metadata_utils.py +22 -23
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/python_type_checking_utils.py +2 -6
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/python_import_rewriter.py +15 -14
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/python_localize_runtime_imports.py +8 -15
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/python_parser_import_index.py +6 -6
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/python_runtime_symbol_collector.py +17 -14
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/python_usage_collector.py +20 -16
- wexample_filestate_python-7.0.0/src/wexample_filestate_python/config_value/python_config_value.py +0 -195
- wexample_filestate_python-7.0.0/src/wexample_filestate_python/option/python/modernize_typing_option.py +0 -25
- wexample_filestate_python-7.0.0/src/wexample_filestate_python/utils/python_attrs_utils.py +0 -111
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/common/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/common/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/common/pipy_gateway.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_option/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_option/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_option/mixin/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_option/mixin/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_value/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/config_value/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/const/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/const/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/const/name_pattern.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/const/path.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/const/python_file.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/event/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/event/src/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/event/src/wexample_event/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/file/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/file/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/helpers/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/helpers/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/helpers/python/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/option/python/abstract_python_file_content_option.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/options_provider/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/options_provider/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/py.typed +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/src/wexample_filestate_python/utils/relocate_imports/__pycache__/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/tests/helpers/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/tests/helpers/test_package.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/tests/helpers/test_toml.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.0}/tests/tests/__init__.py +0 -0
- {wexample_filestate_python-7.0.0 → wexample_filestate_python-8.0.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:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: Helpers for Python.
|
|
5
5
|
Author-Email: weeger <contact@wexample.com>
|
|
6
6
|
License: MIT
|
|
@@ -17,10 +17,9 @@ Requires-Dist: flynt
|
|
|
17
17
|
Requires-Dist: isort
|
|
18
18
|
Requires-Dist: libcst
|
|
19
19
|
Requires-Dist: packaging
|
|
20
|
-
Requires-Dist: pyupgrade
|
|
21
20
|
Requires-Dist: tomli
|
|
22
|
-
Requires-Dist: wexample-api>=6.
|
|
23
|
-
Requires-Dist: wexample-filestate>=
|
|
21
|
+
Requires-Dist: wexample-api>=6.5.0
|
|
22
|
+
Requires-Dist: wexample-filestate>=13.0.0
|
|
24
23
|
Provides-Extra: dev
|
|
25
24
|
Requires-Dist: pytest; extra == "dev"
|
|
26
25
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -28,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
|
28
27
|
|
|
29
28
|
# filestate_python
|
|
30
29
|
|
|
31
|
-
Version:
|
|
30
|
+
Version: 8.0.0
|
|
32
31
|
|
|
33
32
|
Helpers for Python.
|
|
34
33
|
|
|
@@ -116,10 +115,9 @@ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the comp
|
|
|
116
115
|
- isort:
|
|
117
116
|
- libcst:
|
|
118
117
|
- packaging:
|
|
119
|
-
- pyupgrade:
|
|
120
118
|
- tomli:
|
|
121
|
-
- wexample-api: >=6.
|
|
122
|
-
- wexample-filestate: >=
|
|
119
|
+
- wexample-api: >=6.5.0
|
|
120
|
+
- wexample-filestate: >=13.0.0
|
|
123
121
|
|
|
124
122
|
## Versioning & Compatibility Policy
|
|
125
123
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# filestate_python
|
|
2
2
|
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
|
|
5
5
|
Helpers for Python.
|
|
6
6
|
|
|
@@ -88,10 +88,9 @@ Visit the [Wexample Suite documentation](https://docs.wexample.com) for the comp
|
|
|
88
88
|
- isort:
|
|
89
89
|
- libcst:
|
|
90
90
|
- packaging:
|
|
91
|
-
- pyupgrade:
|
|
92
91
|
- tomli:
|
|
93
|
-
- wexample-api: >=6.
|
|
94
|
-
- wexample-filestate: >=
|
|
92
|
+
- wexample-api: >=6.5.0
|
|
93
|
+
- wexample-filestate: >=13.0.0
|
|
95
94
|
|
|
96
95
|
## Versioning & Compatibility Policy
|
|
97
96
|
|
|
@@ -6,7 +6,7 @@ build-backend = "pdm.backend"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "wexample-filestate-python"
|
|
9
|
-
version = "
|
|
9
|
+
version = "8.0.0"
|
|
10
10
|
description = "Helpers for Python."
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "weeger", email = "contact@wexample.com" },
|
|
@@ -26,10 +26,9 @@ dependencies = [
|
|
|
26
26
|
"isort",
|
|
27
27
|
"libcst",
|
|
28
28
|
"packaging",
|
|
29
|
-
"pyupgrade",
|
|
30
29
|
"tomli",
|
|
31
|
-
"wexample-api>=6.
|
|
32
|
-
"wexample-filestate>=
|
|
30
|
+
"wexample-api>=6.5.0",
|
|
31
|
+
"wexample-filestate>=13.0.0",
|
|
33
32
|
]
|
|
34
33
|
|
|
35
34
|
[project.readme]
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import io
|
|
4
|
+
import sys
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
class WithStdoutWrappingMixin:
|
|
5
8
|
@classmethod
|
|
@@ -15,9 +18,6 @@ class WithStdoutWrappingMixin:
|
|
|
15
18
|
Returns:
|
|
16
19
|
The return value of the callback function
|
|
17
20
|
"""
|
|
18
|
-
import io
|
|
19
|
-
import sys
|
|
20
|
-
|
|
21
21
|
old_stdout = sys.stdout
|
|
22
22
|
old_stderr = sys.stderr
|
|
23
23
|
captured_stdout = io.StringIO()
|
|
@@ -34,9 +34,9 @@ class WithStdoutWrappingMixin:
|
|
|
34
34
|
stdout_content = captured_stdout.getvalue()
|
|
35
35
|
stderr_content = captured_stderr.getvalue()
|
|
36
36
|
|
|
37
|
-
if stdout_content.strip():
|
|
37
|
+
if stdout_content and stdout_content.strip():
|
|
38
38
|
sys.stdout.write(stdout_content.rstrip() + "\n\n")
|
|
39
|
-
if stderr_content.strip():
|
|
39
|
+
if stderr_content and stderr_content.strip():
|
|
40
40
|
sys.stderr.write(stderr_content.rstrip() + "\n\n")
|
|
41
41
|
|
|
42
42
|
return result
|
wexample_filestate_python-8.0.0/src/wexample_filestate_python/config_value/python_config_value.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from wexample_config.config_value.config_value import ConfigValue
|
|
6
|
+
from wexample_helpers.classes.field import public_field
|
|
7
|
+
from wexample_helpers.decorator.base_class import base_class
|
|
8
|
+
|
|
9
|
+
# Cached mapping: option-name → self attribute name.
|
|
10
|
+
# Built once on first call to to_option_raw_value() so the 22 deferred
|
|
11
|
+
# imports and get_name() class-method calls are paid only once per process.
|
|
12
|
+
_OPTION_NAME_TO_ATTR: dict[str, str] | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _build_option_name_to_attr() -> dict[str, str]:
|
|
16
|
+
from wexample_filestate_python.config_option.add_future_annotations_config_option import (
|
|
17
|
+
AddFutureAnnotationsConfigOption,
|
|
18
|
+
)
|
|
19
|
+
from wexample_filestate_python.config_option.add_return_types_config_option import (
|
|
20
|
+
AddReturnTypesConfigOption,
|
|
21
|
+
)
|
|
22
|
+
from wexample_filestate_python.config_option.fix_attrs_config_option import (
|
|
23
|
+
FixAttrsConfigOption,
|
|
24
|
+
)
|
|
25
|
+
from wexample_filestate_python.config_option.fix_blank_lines_config_option import (
|
|
26
|
+
FixBlankLinesConfigOption,
|
|
27
|
+
)
|
|
28
|
+
from wexample_filestate_python.config_option.format_config_option import (
|
|
29
|
+
FormatConfigOption,
|
|
30
|
+
)
|
|
31
|
+
from wexample_filestate_python.config_option.fstringify_config_option import (
|
|
32
|
+
FstringifyConfigOption,
|
|
33
|
+
)
|
|
34
|
+
from wexample_filestate_python.config_option.modernize_typing_config_option import (
|
|
35
|
+
ModernizeTypingConfigOption,
|
|
36
|
+
)
|
|
37
|
+
from wexample_filestate_python.config_option.order_class_attributes_config_option import (
|
|
38
|
+
OrderClassAttributesConfigOption,
|
|
39
|
+
)
|
|
40
|
+
from wexample_filestate_python.config_option.order_class_docstring_config_option import (
|
|
41
|
+
OrderClassDocstringConfigOption,
|
|
42
|
+
)
|
|
43
|
+
from wexample_filestate_python.config_option.order_class_methods_config_option import (
|
|
44
|
+
OrderClassMethodsConfigOption,
|
|
45
|
+
)
|
|
46
|
+
from wexample_filestate_python.config_option.order_constants_config_option import (
|
|
47
|
+
OrderConstantsConfigOption,
|
|
48
|
+
)
|
|
49
|
+
from wexample_filestate_python.config_option.order_iterable_items_config_option import (
|
|
50
|
+
OrderIterableItemsConfigOption,
|
|
51
|
+
)
|
|
52
|
+
from wexample_filestate_python.config_option.order_main_guard_config_option import (
|
|
53
|
+
OrderMainGuardConfigOption,
|
|
54
|
+
)
|
|
55
|
+
from wexample_filestate_python.config_option.order_module_docstring_config_option import (
|
|
56
|
+
OrderModuleDocstringConfigOption,
|
|
57
|
+
)
|
|
58
|
+
from wexample_filestate_python.config_option.order_module_functions_config_option import (
|
|
59
|
+
OrderModuleFunctionsConfigOption,
|
|
60
|
+
)
|
|
61
|
+
from wexample_filestate_python.config_option.order_module_metadata_config_option import (
|
|
62
|
+
OrderModuleMetadataConfigOption,
|
|
63
|
+
)
|
|
64
|
+
from wexample_filestate_python.config_option.order_spacing_config_option import (
|
|
65
|
+
OrderSpacingConfigOption,
|
|
66
|
+
)
|
|
67
|
+
from wexample_filestate_python.config_option.order_type_checking_block_config_option import (
|
|
68
|
+
OrderTypeCheckingBlockConfigOption,
|
|
69
|
+
)
|
|
70
|
+
from wexample_filestate_python.config_option.relocate_imports_config_option import (
|
|
71
|
+
RelocateImportsConfigOption,
|
|
72
|
+
)
|
|
73
|
+
from wexample_filestate_python.config_option.remove_unused_config_option import (
|
|
74
|
+
RemoveUnusedConfigOption,
|
|
75
|
+
)
|
|
76
|
+
from wexample_filestate_python.config_option.sort_imports_config_option import (
|
|
77
|
+
SortImportsConfigOption,
|
|
78
|
+
)
|
|
79
|
+
from wexample_filestate_python.config_option.unquote_annotations_config_option import (
|
|
80
|
+
UnquoteAnnotationsConfigOption,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
AddFutureAnnotationsConfigOption.get_name(): "add_future_annotations",
|
|
85
|
+
AddReturnTypesConfigOption.get_name(): "add_return_types",
|
|
86
|
+
FixAttrsConfigOption.get_name(): "fix_attrs",
|
|
87
|
+
FixBlankLinesConfigOption.get_name(): "fix_blank_lines",
|
|
88
|
+
FormatConfigOption.get_name(): "format",
|
|
89
|
+
FstringifyConfigOption.get_name(): "fstringify",
|
|
90
|
+
ModernizeTypingConfigOption.get_name(): "modernize_typing",
|
|
91
|
+
OrderClassAttributesConfigOption.get_name(): "order_class_attributes",
|
|
92
|
+
OrderClassDocstringConfigOption.get_name(): "order_class_docstring",
|
|
93
|
+
OrderClassMethodsConfigOption.get_name(): "order_class_methods",
|
|
94
|
+
OrderConstantsConfigOption.get_name(): "order_constants",
|
|
95
|
+
OrderIterableItemsConfigOption.get_name(): "order_iterable_items",
|
|
96
|
+
OrderMainGuardConfigOption.get_name(): "order_main_guard",
|
|
97
|
+
OrderModuleDocstringConfigOption.get_name(): "order_module_docstring",
|
|
98
|
+
OrderModuleFunctionsConfigOption.get_name(): "order_module_functions",
|
|
99
|
+
OrderModuleMetadataConfigOption.get_name(): "order_module_metadata",
|
|
100
|
+
OrderSpacingConfigOption.get_name(): "order_spacing",
|
|
101
|
+
OrderTypeCheckingBlockConfigOption.get_name(): "order_type_checking_block",
|
|
102
|
+
RelocateImportsConfigOption.get_name(): "relocate_imports",
|
|
103
|
+
RemoveUnusedConfigOption.get_name(): "remove_unused",
|
|
104
|
+
SortImportsConfigOption.get_name(): "sort_imports",
|
|
105
|
+
UnquoteAnnotationsConfigOption.get_name(): "unquote_annotations",
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@base_class
|
|
110
|
+
class PythonConfigValue(ConfigValue):
|
|
111
|
+
add_future_annotations: bool | None = public_field(
|
|
112
|
+
default=None,
|
|
113
|
+
description="Add `from __future__ import annotations`",
|
|
114
|
+
)
|
|
115
|
+
add_return_types: bool | None = public_field(
|
|
116
|
+
default=None,
|
|
117
|
+
description="Add return type annotations",
|
|
118
|
+
)
|
|
119
|
+
fix_attrs: bool | None = public_field(
|
|
120
|
+
default=None,
|
|
121
|
+
description="Fix attrs usage (ensure kw_only=True, etc.)",
|
|
122
|
+
)
|
|
123
|
+
fix_blank_lines: bool | None = public_field(
|
|
124
|
+
default=None,
|
|
125
|
+
description="Fix blank lines in Python files",
|
|
126
|
+
)
|
|
127
|
+
format: bool | None = public_field(
|
|
128
|
+
default=None,
|
|
129
|
+
description="Format Python code",
|
|
130
|
+
)
|
|
131
|
+
fstringify: bool | None = public_field(
|
|
132
|
+
default=None,
|
|
133
|
+
description="Convert string formatting to f-strings",
|
|
134
|
+
)
|
|
135
|
+
modernize_typing: bool | None = public_field(
|
|
136
|
+
default=None,
|
|
137
|
+
description="Modernize typing annotations",
|
|
138
|
+
)
|
|
139
|
+
order_class_attributes: bool | None = public_field(
|
|
140
|
+
default=None,
|
|
141
|
+
description="Sort class attributes: special first, then public A–Z, then private/protected A–Z",
|
|
142
|
+
)
|
|
143
|
+
order_class_docstring: bool | None = public_field(
|
|
144
|
+
default=None,
|
|
145
|
+
description="Ensure class docstring is first statement after header/decorators",
|
|
146
|
+
)
|
|
147
|
+
order_class_methods: bool | None = public_field(
|
|
148
|
+
default=None,
|
|
149
|
+
description="Order class methods (dunders sequence, class/staticmethods, properties, instances)",
|
|
150
|
+
)
|
|
151
|
+
order_constants: bool | None = public_field(
|
|
152
|
+
default=None,
|
|
153
|
+
description="Sort flagged UPPER_CASE constant blocks at module level",
|
|
154
|
+
)
|
|
155
|
+
order_iterable_items: bool | None = public_field(
|
|
156
|
+
default=None,
|
|
157
|
+
description="Sort items inside flagged iterable literals (lists/dicts)",
|
|
158
|
+
)
|
|
159
|
+
order_main_guard: bool | None = public_field(
|
|
160
|
+
default=None,
|
|
161
|
+
description="Ensure if __name__ == '__main__' block is at the very end",
|
|
162
|
+
)
|
|
163
|
+
order_module_docstring: bool | None = public_field(
|
|
164
|
+
default=None,
|
|
165
|
+
description="Order module docstring to be at the top of the file",
|
|
166
|
+
)
|
|
167
|
+
order_module_functions: bool | None = public_field(
|
|
168
|
+
default=None,
|
|
169
|
+
description="Order module-level functions (public A–Z, then private)",
|
|
170
|
+
)
|
|
171
|
+
order_module_metadata: bool | None = public_field(
|
|
172
|
+
default=None,
|
|
173
|
+
description="Group and sort module metadata at module level",
|
|
174
|
+
)
|
|
175
|
+
order_spacing: bool | None = public_field(
|
|
176
|
+
default=None,
|
|
177
|
+
description="Normalize blank lines between program structures (spacing rules)",
|
|
178
|
+
)
|
|
179
|
+
order_type_checking_block: bool | None = public_field(
|
|
180
|
+
default=None,
|
|
181
|
+
description="Move TYPE_CHECKING blocks to after regular imports",
|
|
182
|
+
)
|
|
183
|
+
raw: Any = public_field(
|
|
184
|
+
default=None, description="Disabled raw value for this config."
|
|
185
|
+
)
|
|
186
|
+
relocate_imports: bool | None = public_field(
|
|
187
|
+
default=None,
|
|
188
|
+
description="Relocate imports by usage (runtime-in-method, class property types, type-only)",
|
|
189
|
+
)
|
|
190
|
+
remove_unused: bool | None = public_field(
|
|
191
|
+
default=None,
|
|
192
|
+
description="Remove unused imports",
|
|
193
|
+
)
|
|
194
|
+
sort_imports: bool | None = public_field(
|
|
195
|
+
default=None,
|
|
196
|
+
description="Sort imports",
|
|
197
|
+
)
|
|
198
|
+
unquote_annotations: bool | None = public_field(
|
|
199
|
+
default=None,
|
|
200
|
+
description="Unquote annotations (remove string annotations)",
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def to_option_raw_value(self) -> Any:
|
|
204
|
+
global _OPTION_NAME_TO_ATTR
|
|
205
|
+
if _OPTION_NAME_TO_ATTR is None:
|
|
206
|
+
_OPTION_NAME_TO_ATTR = _build_option_name_to_attr()
|
|
207
|
+
return {
|
|
208
|
+
name: getattr(self, attr)
|
|
209
|
+
for name, attr in _OPTION_NAME_TO_ATTR.items()
|
|
210
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import ast
|
|
4
|
+
import re
|
|
4
5
|
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
import tomli
|
|
@@ -19,32 +20,21 @@ def package_get_dependencies(root_dir: str | Path) -> dict[str, set[str]]:
|
|
|
19
20
|
if not packages_root.exists() or not packages_root.is_dir():
|
|
20
21
|
raise ValueError(f"Error: {packages_root} does not exist or is not a directory")
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# First pass: collect all local packages
|
|
26
|
-
for package_dir in all_entries:
|
|
27
|
-
if not package_dir.is_dir():
|
|
28
|
-
continue
|
|
29
|
-
|
|
30
|
-
package_info = package_get_info(package_dir)
|
|
31
|
-
if package_info:
|
|
32
|
-
name, _ = package_info
|
|
33
|
-
dependencies[name] = set()
|
|
34
|
-
|
|
35
|
-
# Second pass: analyze dependencies
|
|
36
|
-
for package_dir in all_entries:
|
|
37
|
-
if not package_dir.is_dir():
|
|
38
|
-
continue
|
|
23
|
+
# Filter to directories once; avoids repeated is_dir() calls in two passes.
|
|
24
|
+
all_dirs = [e for e in packages_root.iterdir() if e.is_dir()]
|
|
39
25
|
|
|
26
|
+
# Single pass: collect all local package infos (name → raw deps).
|
|
27
|
+
pkg_infos: dict[str, set[str]] = {}
|
|
28
|
+
for package_dir in all_dirs:
|
|
40
29
|
package_info = package_get_info(package_dir)
|
|
41
30
|
if package_info:
|
|
42
31
|
name, deps = package_info
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
pkg_infos[name] = deps
|
|
33
|
+
|
|
34
|
+
local_names: set[str] = set(pkg_infos) # O(1) membership for filtering
|
|
46
35
|
|
|
47
|
-
|
|
36
|
+
# Keep only deps that resolve to a local package (set intersection).
|
|
37
|
+
return {name: deps & local_names for name, deps in pkg_infos.items()}
|
|
48
38
|
|
|
49
39
|
|
|
50
40
|
def package_get_info(package_dir: Path) -> tuple[str, set[str]] | None:
|
|
@@ -72,10 +62,8 @@ def package_get_info(package_dir: Path) -> tuple[str, set[str]] | None:
|
|
|
72
62
|
|
|
73
63
|
|
|
74
64
|
def package_normalize_name(val: str) -> str:
|
|
75
|
-
import re as _re
|
|
76
|
-
|
|
77
65
|
# strip extras, versions, markers
|
|
78
|
-
base =
|
|
66
|
+
base = re.split(r"[\s<>=!~;\[]", val, maxsplit=1)[0]
|
|
79
67
|
return base.strip().lower()
|
|
80
68
|
|
|
81
69
|
|
|
@@ -96,11 +96,12 @@ def toml_sort_string_array(arr: Any) -> bool:
|
|
|
96
96
|
if not items or not all(isinstance(i, String) for i in items):
|
|
97
97
|
return False
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if
|
|
99
|
+
keys = [i.value.lower() for i in items]
|
|
100
|
+
sorted_keys = sorted(keys)
|
|
101
|
+
if keys == sorted_keys:
|
|
102
102
|
return False
|
|
103
103
|
|
|
104
|
+
sorted_items = sorted(items, key=lambda i: i.value.lower())
|
|
104
105
|
multiline_flag = arr._multiline
|
|
105
106
|
# Clear and re-append to preserve tomlkit item identity
|
|
106
107
|
while arr:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import ast
|
|
4
|
+
import re
|
|
3
5
|
from typing import TYPE_CHECKING
|
|
4
6
|
|
|
5
7
|
from wexample_helpers.decorator.base_class import base_class
|
|
@@ -9,6 +11,10 @@ from .abstract_python_file_content_option import AbstractPythonFileContentOption
|
|
|
9
11
|
if TYPE_CHECKING:
|
|
10
12
|
from wexample_filestate.const.types_state_items import TargetFileOrDirectoryType
|
|
11
13
|
|
|
14
|
+
# PEP 263 encoding cookie matcher. Compiled once at import time, reused
|
|
15
|
+
# across every file the rectifier touches.
|
|
16
|
+
_ENCODING_COOKIE_RE = re.compile(r"^#.*coding[:=]\s*([-_.a-zA-Z0-9]+)")
|
|
17
|
+
|
|
12
18
|
|
|
13
19
|
@base_class
|
|
14
20
|
class AddFutureAnnotationsOption(AbstractPythonFileContentOption):
|
|
@@ -23,9 +29,6 @@ class AddFutureAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
23
29
|
if "from __future__ import annotations" in src:
|
|
24
30
|
return src
|
|
25
31
|
|
|
26
|
-
import ast
|
|
27
|
-
import re
|
|
28
|
-
|
|
29
32
|
lines = src.splitlines(keepends=True)
|
|
30
33
|
|
|
31
34
|
# Detect shebang and encoding cookie positions
|
|
@@ -33,9 +36,8 @@ class AddFutureAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
33
36
|
if lines and lines[0].startswith("#!"):
|
|
34
37
|
idx = 1
|
|
35
38
|
# Encoding cookie can be on first or second line (after shebang)
|
|
36
|
-
enc_re = re.compile(r"^#.*coding[:=]\s*([-_.a-zA-Z0-9]+)")
|
|
37
39
|
for i in range(idx, min(idx + 2, len(lines))):
|
|
38
|
-
if
|
|
40
|
+
if _ENCODING_COOKIE_RE.match(lines[i]):
|
|
39
41
|
idx = i + 1
|
|
40
42
|
|
|
41
43
|
# Parse to find module docstring span
|
|
@@ -45,11 +47,11 @@ class AddFutureAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
45
47
|
# If parsing fails, be conservative: insert after header block
|
|
46
48
|
insert_at = idx
|
|
47
49
|
else:
|
|
48
|
-
body =
|
|
50
|
+
body = tree.body
|
|
49
51
|
if (
|
|
50
52
|
body
|
|
51
53
|
and isinstance(body[0], ast.Expr)
|
|
52
|
-
and isinstance(
|
|
54
|
+
and isinstance(body[0].value, ast.Constant)
|
|
53
55
|
and isinstance(body[0].value.value, str)
|
|
54
56
|
):
|
|
55
57
|
# Module docstring present; insert after its end_lineno
|
|
@@ -59,7 +61,7 @@ class AddFutureAnnotationsOption(AbstractPythonFileContentOption):
|
|
|
59
61
|
insert_at = idx
|
|
60
62
|
|
|
61
63
|
# lines is 0-based; insert_at is 1-based line count from AST
|
|
62
|
-
insert_index =
|
|
64
|
+
insert_index = min(len(lines), insert_at)
|
|
63
65
|
|
|
64
66
|
# Ensure there is a newline after the inserted import if needed
|
|
65
67
|
future_line = "from __future__ import annotations\n"
|
|
@@ -26,10 +26,7 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
26
26
|
get_python_source_and_module,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
src, module = get_python_source_and_module(target)
|
|
31
|
-
except Exception:
|
|
32
|
-
return target.get_local_file().read()
|
|
29
|
+
src, module = get_python_source_and_module(target)
|
|
33
30
|
|
|
34
31
|
# We implement type inference and rewriting using LibCST to ensure
|
|
35
32
|
# robust, formatting-preserving edits. We extend inference to:
|
|
@@ -50,9 +47,33 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
50
47
|
return "float"
|
|
51
48
|
return None
|
|
52
49
|
|
|
50
|
+
def _infer_class_call_type(call: cst.Call, known_types: set[str]) -> str | None:
|
|
51
|
+
"""Return the class name if `call` instantiates a known type.
|
|
52
|
+
|
|
53
|
+
Recognizes `Foo()` and `module.Foo()` shapes; requires the matched
|
|
54
|
+
name to be uppercase-first to stay conservative. Single source of
|
|
55
|
+
truth shared by the assignment collector and the return-expression
|
|
56
|
+
transformer.
|
|
57
|
+
"""
|
|
58
|
+
func = call.func
|
|
59
|
+
if isinstance(func, cst.Name):
|
|
60
|
+
if func.value in known_types and func.value[:1].isupper():
|
|
61
|
+
return func.value
|
|
62
|
+
return None
|
|
63
|
+
if isinstance(func, cst.Attribute) and isinstance(func.attr, cst.Name):
|
|
64
|
+
attr_name = func.attr.value
|
|
65
|
+
if attr_name in known_types and attr_name[:1].isupper():
|
|
66
|
+
return attr_name
|
|
67
|
+
return None
|
|
68
|
+
|
|
53
69
|
class _ReturnCollector(cst.CSTVisitor):
|
|
54
70
|
def __init__(self) -> None:
|
|
55
71
|
self.returns: list[cst.Return] = []
|
|
72
|
+
# A function with any `yield` / `yield from` is a generator —
|
|
73
|
+
# its real return type is Iterator[X], not whatever the return
|
|
74
|
+
# statements imply. We can't infer Iterator[X] from this simple
|
|
75
|
+
# pass, so we record the flag and bail out at the caller.
|
|
76
|
+
self.has_yield: bool = False
|
|
56
77
|
|
|
57
78
|
# Do not descend into nested scopes that could have their own returns
|
|
58
79
|
def visit_FunctionDef(self, node: cst.FunctionDef) -> bool: # type: ignore[override]
|
|
@@ -67,6 +88,11 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
67
88
|
def visit_Return(self, node: cst.Return) -> None: # type: ignore[override]
|
|
68
89
|
self.returns.append(node)
|
|
69
90
|
|
|
91
|
+
def visit_Yield(self, node: cst.Yield) -> None: # type: ignore[override]
|
|
92
|
+
# libcst represents `yield from X` as a Yield whose value is
|
|
93
|
+
# `cst.From(item=X)`, so this single hook catches both forms.
|
|
94
|
+
self.has_yield = True
|
|
95
|
+
|
|
70
96
|
class _KnownTypesCollector(cst.CSTVisitor):
|
|
71
97
|
"""Collect known simple type names from class defs and from-imports.
|
|
72
98
|
|
|
@@ -103,20 +129,6 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
103
129
|
self.var_type: dict[str, str] = {}
|
|
104
130
|
self.discarded: set[str] = set()
|
|
105
131
|
|
|
106
|
-
def _infer_call_type(self, call: cst.Call) -> str | None:
|
|
107
|
-
func = call.func
|
|
108
|
-
if isinstance(func, cst.Name):
|
|
109
|
-
# Only keep conservative matches: known type names
|
|
110
|
-
if func.value in self.known_types and func.value[:1].isupper():
|
|
111
|
-
return func.value
|
|
112
|
-
elif isinstance(func, cst.Attribute):
|
|
113
|
-
# module.MyClass(...) -> infer MyClass if it's a known type
|
|
114
|
-
if isinstance(func.attr, cst.Name):
|
|
115
|
-
attr_name = func.attr.value
|
|
116
|
-
if attr_name in self.known_types and attr_name[:1].isupper():
|
|
117
|
-
return attr_name
|
|
118
|
-
return None
|
|
119
|
-
|
|
120
132
|
def _record_assignment(
|
|
121
133
|
self, target: cst.BaseExpression, value: cst.BaseExpression
|
|
122
134
|
) -> None:
|
|
@@ -127,7 +139,7 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
127
139
|
return
|
|
128
140
|
if not isinstance(value, cst.Call):
|
|
129
141
|
return
|
|
130
|
-
rtype = self.
|
|
142
|
+
rtype = _infer_class_call_type(value, self.known_types)
|
|
131
143
|
if rtype is None:
|
|
132
144
|
return
|
|
133
145
|
existing = self.var_type.get(var)
|
|
@@ -170,20 +182,7 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
170
182
|
|
|
171
183
|
# Call to a known class
|
|
172
184
|
if isinstance(expr, cst.Call):
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
isinstance(func, cst.Name)
|
|
176
|
-
and func.value in self.known_types
|
|
177
|
-
and func.value[:1].isupper()
|
|
178
|
-
):
|
|
179
|
-
return func.value
|
|
180
|
-
if isinstance(func, cst.Attribute) and isinstance(
|
|
181
|
-
func.attr, cst.Name
|
|
182
|
-
):
|
|
183
|
-
attr_name = func.attr.value
|
|
184
|
-
if attr_name in self.known_types and attr_name[:1].isupper():
|
|
185
|
-
return attr_name
|
|
186
|
-
return None
|
|
185
|
+
return _infer_class_call_type(expr, self.known_types)
|
|
187
186
|
|
|
188
187
|
# Variable referring to a previously inferred var type
|
|
189
188
|
if isinstance(expr, cst.Name):
|
|
@@ -194,9 +193,12 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
194
193
|
def _infer_for_function(self, func_node: cst.FunctionDef) -> str | None:
|
|
195
194
|
# Collect returns in the function body (non-nested)
|
|
196
195
|
collector = _ReturnCollector()
|
|
197
|
-
if not isinstance(func_node, cst.FunctionDef):
|
|
198
|
-
return None
|
|
199
196
|
func_node.body.visit(collector)
|
|
197
|
+
# Generator: never annotate via this simple pass. The function
|
|
198
|
+
# actually returns Iterator[X] / Generator[X, ...], which we
|
|
199
|
+
# can't infer here — leave it unannotated for a human to fill.
|
|
200
|
+
if collector.has_yield:
|
|
201
|
+
return None
|
|
200
202
|
# If no return statements -> None
|
|
201
203
|
if not collector.returns:
|
|
202
204
|
return "None"
|
|
@@ -216,7 +218,7 @@ class AddReturnTypesOption(AbstractPythonFileContentOption):
|
|
|
216
218
|
kinds.add(inferred)
|
|
217
219
|
|
|
218
220
|
if len(kinds) == 1:
|
|
219
|
-
return
|
|
221
|
+
return kinds.pop()
|
|
220
222
|
return None
|
|
221
223
|
|
|
222
224
|
def leave_FunctionDef(
|
|
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
|
|
18
18
|
class ClassNameMatchesFileNameOption(OptionMixin, AbstractConfigOption):
|
|
19
19
|
@classmethod
|
|
20
20
|
def get_scopes(cls) -> list[Scope]:
|
|
21
|
-
return [Scope.NAME]
|
|
21
|
+
return [Scope.NAME, Scope.CONTENT]
|
|
22
22
|
|
|
23
23
|
@staticmethod
|
|
24
24
|
def _expected_class_name_from_path(path: Path) -> str | None:
|
|
@@ -31,12 +31,13 @@ class ClassNameMatchesFileNameOption(OptionMixin, AbstractConfigOption):
|
|
|
31
31
|
if not parts:
|
|
32
32
|
return None
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
head, tail = part[:1], part[1:]
|
|
36
|
-
return head.upper() + tail.lower()
|
|
37
|
-
|
|
34
|
+
normalize = ClassNameMatchesFileNameOption._normalize_part
|
|
38
35
|
return "".join(normalize(part) for part in parts)
|
|
39
36
|
|
|
37
|
+
@staticmethod
|
|
38
|
+
def _normalize_part(part: str) -> str:
|
|
39
|
+
return part[:1].upper() + part[1:].lower()
|
|
40
|
+
|
|
40
41
|
def create_required_operation(
|
|
41
42
|
self, target: TargetFileOrDirectoryType, scopes: set[Scope]
|
|
42
43
|
) -> AbstractOperation | None:
|
|
@@ -63,7 +64,7 @@ class ClassNameMatchesFileNameOption(OptionMixin, AbstractConfigOption):
|
|
|
63
64
|
except SyntaxError:
|
|
64
65
|
return False
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
return any(
|
|
68
|
+
isinstance(node, ast.ClassDef) and node.name == expected_name
|
|
69
|
+
for node in module.body
|
|
70
|
+
)
|
|
@@ -41,7 +41,6 @@ class FixBlankLinesOption(AbstractPythonFileContentOption):
|
|
|
41
41
|
fix_function_blank_lines,
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
_, module = get_python_source_and_module(target)
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
return modified.code
|
|
46
|
+
return fix_function_blank_lines(module).code
|