Skip to content

Commit cb3d9d3

Browse files
committed
adding more tests, refactoring
1 parent 12305a2 commit cb3d9d3

22 files changed

+1456
-468
lines changed

.flake8

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
max-line-length = 130

.github/workflows/cd.yml

Lines changed: 134 additions & 105 deletions
Large diffs are not rendered by default.

.github/workflows/ci.yml

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# .github/workflows/ci.yml
12
name: TreeMapper CI
23

34
on:
@@ -8,13 +9,57 @@ on:
89
- main
910

1011
jobs:
12+
# --- Задание для проверки качества кода ---
13+
lint-type-check:
14+
name: Lint & Type Check
15+
runs-on: ubuntu-latest # Достаточно одной ОС/версии Python
16+
steps:
17+
- name: Checkout Code
18+
uses: actions/checkout@v3
19+
20+
- name: Set up Python 3.11 # Используем одну из последних версий для проверок
21+
uses: actions/setup-python@v4
22+
with:
23+
python-version: '3.11'
24+
25+
- name: Cache pip Dependencies
26+
uses: actions/cache@v3
27+
with:
28+
# Используем setup.cfg для ключа кэша
29+
path: ~/.cache/pip
30+
key: ${{ runner.os }}-lint-pip-${{ hashFiles('**/setup.cfg') }}
31+
restore-keys: |
32+
${{ runner.os }}-lint-pip-
33+
34+
- name: Install Linters and Type Checker
35+
run: |
36+
python -m pip install --upgrade pip
37+
# Устанавливаем только dev-зависимости из setup.cfg
38+
pip install .[dev]
39+
# Если нужные пакеты не в [dev], добавьте: pip install flake8 black isort mypy types-PyYAML
40+
41+
- name: Run Linters and Formatters Check
42+
run: |
43+
flake8 src tests
44+
black --check src tests
45+
isort --check-only src tests
46+
47+
- name: Run Type Checker (Mypy)
48+
run: |
49+
# Mypy может требовать установленных зависимостей для корректной проверки
50+
mypy src tests
51+
52+
# --- Задание для тестов на CPython ---
1153
test:
54+
needs: lint-type-check # Запускаем тесты ПОСЛЕ проверки качества кода
1255
strategy:
56+
fail-fast: false # Не отменять другие тесты при падении одного
1357
matrix:
14-
os: [ ubuntu-latest, ubuntu-20.04, ubuntu-22.04, macos-latest, windows-latest ]
15-
python-version: [ 3.9, '3.10', '3.11' ]
58+
os: [ ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, macos-latest, windows-latest ]
59+
python-version: [ 3.9, '3.10', '3.11', '3.12' ]
1660

1761
runs-on: ${{ matrix.os }}
62+
# continue-on-error: ${{ matrix.experimental || false }} # Опционально для 3.13
1863

1964
steps:
2065
- name: Checkout Code
@@ -29,33 +74,46 @@ jobs:
2974
uses: actions/cache@v3
3075
with:
3176
path: ~/.cache/pip
32-
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.cfg') }}
77+
# Ключ кэша включает ОС, версию Python и хэш setup.cfg
78+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.cfg') }}
3379
restore-keys: |
80+
${{ runner.os }}-pip-${{ matrix.python-version }}-
3481
${{ runner.os }}-pip-
3582
3683
- name: Install Dependencies
3784
run: |
3885
python -m pip install --upgrade pip
39-
pip install -r requirements.txt
40-
pip install -e .
86+
# Устанавливаем пакет и dev-зависимости из setup.cfg
87+
pip install -e .[dev]
4188
42-
- name: Build with PyInstaller
43-
run: |
44-
python -m PyInstaller --clean -y --dist ./dist/${{ runner.os }} --workpath /tmp treemapper.spec
45-
46-
- name: Build with python -m build
47-
run: |
48-
python -m build
89+
# --- Шаги сборки PyInstaller и build УДАЛЕНЫ ---
4990

50-
- name: Run Tests
91+
- name: Run Tests with Coverage
5192
run: |
52-
pytest
93+
# Запускаем pytest с генерацией отчета покрытия в формате XML
94+
pytest -v --cov=src/treemapper --cov-report=xml
95+
96+
- name: Upload coverage reports to Codecov
97+
# Запускаем только для одной комбинации, чтобы не дублировать отчеты
98+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
99+
uses: codecov/codecov-action@v4
100+
# Не требует токена для публичных репозиториев на github.com
101+
# env:
102+
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} # Для приватных репо
103+
with:
104+
files: ./coverage.xml # Файл отчета, созданный pytest-cov
105+
fail_ci_if_error: true
106+
verbose: true
53107

108+
# --- Задание для тестов на PyPy ---
54109
test-pypy:
110+
needs: lint-type-check # Запускаем тесты ПОСЛЕ проверки качества кода
55111
runs-on: ubuntu-latest
56112
strategy:
113+
fail-fast: false
57114
matrix:
58-
python-version: [ pypy-3.9 ]
115+
# Добавлена версия PyPy 3.10 (проверьте доступность в actions/setup-python)
116+
python-version: [ pypy-3.9, pypy-3.10 ]
59117

60118
steps:
61119
- name: Checkout Code
@@ -70,21 +128,19 @@ jobs:
70128
uses: actions/cache@v3
71129
with:
72130
path: ~/.cache/pip
73-
key: pypy-pip-${{ hashFiles('**/setup.cfg') }}
131+
key: pypy-${{ matrix.python-version }}-pip-${{ hashFiles('**/setup.cfg') }}
74132
restore-keys: |
75-
pypy-pip-
133+
pypy-${{ matrix.python-version }}-pip-
76134
77135
- name: Install Dependencies
78136
run: |
79137
python -m pip install --upgrade pip
80-
pip install -r requirements.txt
81-
pip install -e .
82-
pip install build pytest
138+
# Устанавливаем с dev зависимостями из setup.cfg
139+
pip install -e .[dev]
140+
# build и pytest теперь должны быть в [dev]
83141
84-
- name: Build with python -m build
85-
run: |
86-
python -m build
142+
# --- Шаг сборки build УДАЛЕН ---
87143

88144
- name: Run Tests
89145
run: |
90-
pytest
146+
pytest -v # Запускаем тесты без покрытия для PyPy, если оно не настроено

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[build-system]
22
requires = ["setuptools>=45", "wheel"]
3-
build-backend = "setuptools.build_meta"
3+
build-backend = "setuptools.build_meta"
4+
5+
[tool.black]
6+
line-length = 130

requirements.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.

setup.cfg

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,28 @@ package_dir =
1818
packages = find:
1919
python_requires = >=3.9
2020
install_requires =
21-
pathspec
22-
pyyaml
21+
pathspec>=0.9
22+
pyyaml>=5.4
2323

2424
[options.packages.find]
2525
where = src
2626

2727
[options.entry_points]
2828
console_scripts =
29-
treemapper = treemapper.treemapper:main
29+
treemapper = treemapper.treemapper:main
30+
31+
[options.extras_require]
32+
dev =
33+
pytest>=7.0
34+
pytest-cov>=3.0
35+
build>=0.10
36+
twine>=4.0
37+
pyinstaller>=5.0
38+
flake8>=5.0
39+
black>=23.0
40+
isort>=5.10
41+
mypy>=1.0
42+
types-PyYAML
43+
pyyaml
44+
pathspec
45+
autoflake

src/treemapper/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
from .treemapper import main
2-
from .version import __version__

src/treemapper/cli.py

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,88 @@
1+
# src/treemapper/cli.py
12
import argparse
23
import sys
34
from pathlib import Path
4-
from typing import Tuple
5+
from typing import Optional, Tuple # <--- Добавлен Optional
56

67

7-
def parse_args() -> Tuple[Path, Path, Path, bool, int]:
8+
# ---> ИЗМЕНЕНИЕ: Заменяем | None на Optional[...] <---
9+
def parse_args() -> Tuple[Path, Optional[Path], Optional[Path], bool, int]:
810
"""Parse command line arguments."""
911
parser = argparse.ArgumentParser(
12+
prog="treemapper",
1013
description="Generate a YAML representation of a directory structure.",
11-
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
14+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
15+
)
1216

13-
parser.add_argument(
14-
"directory",
15-
nargs="?",
16-
default=".",
17-
help="The directory to analyze")
17+
parser.add_argument("directory", nargs="?", default=".", help="The directory to analyze")
1818

1919
parser.add_argument(
20-
"-i", "--ignore-file",
20+
"-i",
21+
"--ignore-file",
2122
default=None,
22-
help="Path to the custom ignore file (optional)")
23+
help="Path to the custom ignore file (optional)",
24+
)
2325

2426
parser.add_argument(
25-
"-o", "--output-file",
27+
"-o",
28+
"--output-file",
2629
default="./directory_tree.yaml",
27-
help="Path to the output YAML file")
30+
help="Path to the output YAML file",
31+
)
2832

2933
parser.add_argument(
3034
"--no-default-ignores",
3135
action="store_true",
32-
help="Disable all default ignores (including .gitignore and .treemapperignore)")
36+
help="Disable default ignores (.treemapperignore, .gitignore, output file)",
37+
)
3338

3439
parser.add_argument(
35-
"-v", "--verbosity",
40+
"-v",
41+
"--verbosity",
3642
type=int,
3743
choices=range(0, 4),
3844
default=2,
3945
metavar="[0-3]",
40-
help="Set verbosity level (0: ERROR, 1: WARNING, 2: INFO, 3: DEBUG)")
46+
help="Set verbosity level (0: ERROR, 1: WARNING, 2: INFO, 3: DEBUG)",
47+
)
4148

4249
args = parser.parse_args()
4350

44-
root_dir = Path(args.directory).resolve()
45-
if not root_dir.is_dir():
46-
print(f"Error: The path '{root_dir}' is not a valid directory.")
51+
try:
52+
root_dir = Path(args.directory).resolve(strict=True)
53+
if not root_dir.is_dir():
54+
print(
55+
f"Error: The path '{root_dir}' is not a valid directory.",
56+
file=sys.stderr,
57+
)
58+
sys.exit(1)
59+
except FileNotFoundError:
60+
print(
61+
f"Error: The directory '{args.directory}' does not exist.",
62+
file=sys.stderr,
63+
)
64+
sys.exit(1)
65+
except Exception as e:
66+
print(
67+
f"Error resolving directory path '{args.directory}': {e}",
68+
file=sys.stderr,
69+
)
4770
sys.exit(1)
4871

4972
output_file = Path(args.output_file)
5073
if not output_file.is_absolute():
5174
output_file = Path.cwd() / output_file
5275

53-
ignore_file = Path(args.ignore_file) if args.ignore_file else None
76+
ignore_file_path: Optional[Path] = None # Используем Optional для ясности
77+
if args.ignore_file:
78+
ignore_file_path = Path(args.ignore_file)
79+
if not ignore_file_path.is_absolute():
80+
ignore_file_path = Path.cwd() / ignore_file_path
5481

55-
return root_dir, ignore_file, output_file, args.no_default_ignores, args.verbosity
82+
return (
83+
root_dir,
84+
ignore_file_path,
85+
output_file,
86+
args.no_default_ignores,
87+
args.verbosity,
88+
)

0 commit comments

Comments
 (0)