Skip to content

Commit

Permalink
Make pycln run with Python 3.12 (#221) (#224)
Browse files Browse the repository at this point in the history
* Fix: Adjust tests for removal of distutils in Python 3.12 (#221)

* Fix: Support changed pathlib in Python 3.12 (#221)

* Fix: run Black on utils package.

* Fix: reverse Python version comparison to make clearer that old behavior is exceptional case

Co-authored-by: Johan Alpne <johan.alpne@funnel.io>

* Add: py3.12 to the ci system

* Add: docs

---------

Co-authored-by: Johan Alpne <johan.alpne@funnel.io>
Co-authored-by: Hadi Alqattan <alqattanhadizaki@gmail.com>
  • Loading branch information
3 people committed Nov 14, 2023
1 parent 6770dd0 commit 56d1e8b
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, windows-latest, macos-latest]
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.12"]

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions docs/AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<!-- - First Last ([@username](https://github.com/username)) <example@email.com> -->

- Alex Waygood ([@AlexWaygood](https://github.com/AlexWaygood)) <Alex.Waygood@gmail.com>
- Per Fagrell ([@perfa](https://github.com/perfa)) <per.fagrell@gmail.com>
- Perchun Pak ([@PerchunPak](https://github.com/PerchunPak)) <perchunpak@gmail.com>
- Pierre Mourlanne ([@pmourlanne](https://github.com/pmourlanne)) <pmourlanne@gmail.com>
- RooTer Urbański ([@rooterkyberian](https://github.com/rooterkyberian))
Expand Down
6 changes: 6 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

## Added

- [Add support for Python 3.12 by @perfa](https://github.com/hadialqattan/pycln/pull/224)

## Changed

- [Drop Python3.6 by @hadialqattan](https://github.com/hadialqattan/pycln/pull/225)

## [2.3.0] - 2023-10-14
Expand Down
5 changes: 0 additions & 5 deletions pycln/utils/pathu.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,13 @@ def get_standard_lib_paths() -> Set[Path]:
paths: Set[Path] = set()

for lib_path in PYTHON_STDLIB_PATHS:

for path in os.listdir(lib_path):
paths.add(Path(os.path.join(lib_path, path)))

# Get lib dynload modules paths, if exists.
lib_dynload_path = os.path.join(lib_path, LIB_DYNLOAD)

if os.path.isdir(lib_dynload_path):

for path in os.listdir(lib_dynload_path):
paths.add(Path(os.path.join(lib_dynload_path, path)))

Expand All @@ -160,7 +158,6 @@ def get_standard_lib_names() -> Set[str]:
paths: Set[Path] = get_standard_lib_paths()

for path in paths:

name = str(path.parts[-1])

if name.startswith("_") or "-" in name:
Expand Down Expand Up @@ -194,7 +191,6 @@ def get_third_party_lib_paths() -> Tuple[Set[Path], Set[Path]]:
packages_paths.add(path)

for path in packages_paths:

for name in os.listdir(path):
if name.endswith(PTH_EXTENSION):
for pth_path in _site.addpackage(path, name):
Expand All @@ -220,7 +216,6 @@ def get_local_import_path(path: Path, module: str) -> Optional[Path]:

# Test different levels.
for i in [None] + list(range(-10, -0)): # type: ignore

# If it's a file.
fpath = os.path.join(*dirnames[:i], *names[:-1], f"{names[-1]}{PY_EXTENSION}")
if os.path.isfile(fpath):
Expand Down
23 changes: 15 additions & 8 deletions pycln/utils/refactor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Pycln code refactoring utility."""
import ast
import os
import sys
from importlib import import_module
from pathlib import Path, _posix_flavour, _windows_flavour # type: ignore
from typing import Iterable, List, Optional, Set, Tuple, Union, cast

from .. import ISWIN
Expand All @@ -20,6 +20,15 @@
from .config import Config
from .report import Report

if sys.version_info < (3, 12):
from pathlib import Path, _posix_flavour, _windows_flavour # type: ignore

_flavour = _windows_flavour if ISWIN else _posix_flavour
else:
from pathlib import Path

_flavour = os.path

# Constants.
NOPYCLN = "nopycln"
CHANGE_MARK = "\n_CHANGED_"
Expand All @@ -28,13 +37,15 @@


class PyPath(Path):

"""Path subclass that has `is_stub` property."""

_flavour = _windows_flavour if ISWIN else _posix_flavour
_flavour = _flavour

def __init__(self, *args) -> None: # pylint: disable=unused-argument
super().__init__() # Path.__init__ does not take any args.
if sys.version_info < (3, 12):
super().__init__() # Path.__init__ does not take any args.
else:
super().__init__(*args)
self._is_stub = regexu.is_stub_file(self)

@property
Expand Down Expand Up @@ -128,7 +139,6 @@ def remove_from_children(

tree = ast.parse("".join(source_lines))
for parent in ast.walk(tree):

body = getattr(parent, "body", None)
if body and hasattr(body, "__len__"):
body_len = len(body)
Expand Down Expand Up @@ -272,9 +282,7 @@ def _refactor(self, original_lines: List[str]) -> str:
"""
fixed_lines = original_lines.copy()
for type_ in self._import_stats:

for node in type_:

# Skip any import that has `# noqa` or `# nopycln: import` comment.
s_lineno = node.location.start.line - 1
e_lineno = node.location.end.line - 1
Expand Down Expand Up @@ -399,7 +407,6 @@ def _expand_import_star(
try:
is_star = False
if node.names[0].name == "*":

#: [for `.pyi` files] PEP 484 - Star Imports rule:
#:
#: >>> from X import * # exported (should be treated as used)
Expand Down
2 changes: 0 additions & 2 deletions pycln/utils/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,6 @@ def _add_list_names(self, node: List[ast.expr]) -> None:
def _compute_not_importables(self, node: Union[FunctionDefT, ast.ClassDef]):
# Compute class/function not-importables.
for node_ in ast.iter_child_nodes(node):

if isinstance(node_, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
self._not_importables.add(cast(str, node_.name))

Expand Down Expand Up @@ -857,7 +856,6 @@ def visit_ImportFrom(self, node: ast.ImportFrom):
def _check_names(names: List[ast.alias]) -> HasSideEffects:
# Check if imported names has side effects or not.
for alias in names:

# All standard lib modules doesn't has side effects
# except `pathu.IMPORTS_WITH_SIDE_EFFECTS`.
if alias.name in pathu.get_standard_lib_names():
Expand Down
8 changes: 4 additions & 4 deletions tests/test_pathu.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ def test_get_module_path(self, paths, module, expec_path):
id="import file : local",
),
pytest.param(
"distutils",
Path("distutils/__init__.py"),
"asyncio",
Path("asyncio/__init__.py"),
id="import module : standard",
),
pytest.param(
Expand Down Expand Up @@ -453,9 +453,9 @@ def test_get_import_path(self, module: str, expec_path: Path):
),
pytest.param(
"*",
"distutils",
"asyncio",
0,
Path("distutils/__init__.py"),
Path("asyncio/__init__.py"),
id="from package import * : standard",
),
pytest.param(
Expand Down

0 comments on commit 56d1e8b

Please sign in to comment.