package-maximizer 0.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.
Files changed (35) hide show
  1. package_maximizer-0.0.0/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
  2. package_maximizer-0.0.0/.github/ISSUE_TEMPLATE/feature_request.md +16 -0
  3. package_maximizer-0.0.0/.github/workflows/ci.yml +64 -0
  4. package_maximizer-0.0.0/.github/workflows/publish.yml +40 -0
  5. package_maximizer-0.0.0/.gitignore +160 -0
  6. package_maximizer-0.0.0/Dockerfile +50 -0
  7. package_maximizer-0.0.0/LICENSE +21 -0
  8. package_maximizer-0.0.0/Makefile +48 -0
  9. package_maximizer-0.0.0/PKG-INFO +98 -0
  10. package_maximizer-0.0.0/README.md +46 -0
  11. package_maximizer-0.0.0/package_maximizer/__init__.py +29 -0
  12. package_maximizer-0.0.0/package_maximizer/analyzers/__init__.py +0 -0
  13. package_maximizer-0.0.0/package_maximizer/cli/__init__.py +0 -0
  14. package_maximizer-0.0.0/package_maximizer/config/__init__.py +0 -0
  15. package_maximizer-0.0.0/package_maximizer/core/__init__.py +17 -0
  16. package_maximizer-0.0.0/package_maximizer/core/enums.py +33 -0
  17. package_maximizer-0.0.0/package_maximizer/core/interfaces.py +33 -0
  18. package_maximizer-0.0.0/package_maximizer/core/maximizer.py +58 -0
  19. package_maximizer-0.0.0/package_maximizer/core/package.py +41 -0
  20. package_maximizer-0.0.0/package_maximizer/parsers/__init__.py +0 -0
  21. package_maximizer-0.0.0/package_maximizer/solvers/__init__.py +0 -0
  22. package_maximizer-0.0.0/package_maximizer/utils/__init__.py +0 -0
  23. package_maximizer-0.0.0/package_maximizer/web/__init__.py +3 -0
  24. package_maximizer-0.0.0/package_maximizer/web/app.py +43 -0
  25. package_maximizer-0.0.0/package_maximizer.egg-info/PKG-INFO +98 -0
  26. package_maximizer-0.0.0/package_maximizer.egg-info/SOURCES.txt +33 -0
  27. package_maximizer-0.0.0/package_maximizer.egg-info/dependency_links.txt +1 -0
  28. package_maximizer-0.0.0/package_maximizer.egg-info/entry_points.txt +3 -0
  29. package_maximizer-0.0.0/package_maximizer.egg-info/requires.txt +30 -0
  30. package_maximizer-0.0.0/package_maximizer.egg-info/top_level.txt +1 -0
  31. package_maximizer-0.0.0/pyproject.toml +69 -0
  32. package_maximizer-0.0.0/requirements.txt +34 -0
  33. package_maximizer-0.0.0/setup.cfg +4 -0
  34. package_maximizer-0.0.0/tests/__init__.py +0 -0
  35. package_maximizer-0.0.0/tests/test_basic.py +26 -0
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: Bug report
3
+ about: Создать отчет об ошибке
4
+ title: '[BUG] '
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ **Описание ошибки**
10
+ Четкое и краткое описание ошибки.
11
+
12
+ **Шаги для воспроизведения**
13
+ 1. Перейти к '...'
14
+ 2. Кликнуть на '....'
15
+ 3. Прокрутить до '....'
16
+ 4. Увидеть ошибку
17
+
18
+ **Ожидаемое поведение**
19
+ Описание того, что должно происходить.
20
+
21
+ **Скриншоты**
22
+ При необходимости добавьте скриншоты.
23
+
24
+ **Окружение:**
25
+ - ОС: [например iOS]
26
+ - Версия Python: [например 3.9]
27
+ - Версия Package Maximizer: [например 0.1.0]
28
+
29
+ **Дополнительная информация**
30
+ Любая другая информация об ошибке.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: Feature request
3
+ about: Предложить идею для проекта
4
+ title: '[FEATURE] '
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ **Связана ли ваша функция с проблемой?**
10
+ Четкое и краткое описание проблемы.
11
+
12
+ **Опишите решение которое вы хотите**
13
+ Четкое и краткое описание того, что вы хотите.
14
+
15
+ **Дополнительная информация**
16
+ Любой другой контекст или скриншоты о запросе функции.
@@ -0,0 +1,64 @@
1
+ name: Package Maximizer CI/CD
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main ]
8
+ release:
9
+ types: [ published ]
10
+
11
+ env:
12
+ PYTHON_VERSION: "3.9"
13
+
14
+ jobs:
15
+ test:
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ matrix:
19
+ os: [ubuntu-latest, windows-latest, macos-latest]
20
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v3
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ uses: actions/setup-python@v4
27
+ with:
28
+ python-version: ${{ matrix.python-version }}
29
+
30
+ - name: Cache pip packages
31
+ uses: actions/cache@v3
32
+ with:
33
+ path: ~/.cache/pip
34
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
35
+ restore-keys: |
36
+ ${{ runner.os }}-pip-
37
+
38
+ - name: Install system dependencies (Ubuntu)
39
+ if: matrix.os == 'ubuntu-latest'
40
+ run: |
41
+ sudo apt-get update
42
+ sudo apt-get install -y gcc g++ libffi-dev
43
+
44
+ - name: Install Python dependencies
45
+ run: |
46
+ python -m pip install --upgrade pip
47
+ pip install -r requirements.txt
48
+ pip install -e ".[dev,all]"
49
+
50
+ - name: Lint with flake8
51
+ run: |
52
+ flake8 package_maximizer/ tests/ --count --select=E9,F63,F7,F82 --show-source --statistics
53
+ flake8 package_maximizer/ tests/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
54
+
55
+ - name: Test with pytest
56
+ run: |
57
+ pytest tests/ -v --cov=package_maximizer --cov-report=xml --cov-report=term
58
+
59
+ - name: Upload coverage to Codecov
60
+ uses: codecov/codecov-action@v3
61
+ with:
62
+ file: ./coverage.xml
63
+ flags: unittests
64
+ name: codecov-${{ matrix.os }}-py${{ matrix.python-version }}
@@ -0,0 +1,40 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+ workflow_dispatch:
6
+
7
+ permissions: {}
8
+
9
+ jobs:
10
+ build:
11
+ name: Build distribution
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with: {fetch-depth: 0}
16
+ - uses: actions/setup-python@v5
17
+ with: {python-version: "3.11"}
18
+ - name: Install build tools
19
+ run: python -m pip install --upgrade build setuptools_scm
20
+ - name: Build sdist and wheel
21
+ run: python -m build
22
+ - uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist/
26
+
27
+ pypi-publish:
28
+ name: Upload to PyPI (trusted publishing)
29
+ needs: build
30
+ runs-on: ubuntu-latest
31
+ environment:
32
+ name: pypi
33
+ url: https://pypi.org/p/package-maximizer
34
+ permissions:
35
+ id-token: write
36
+ steps:
37
+ - uses: actions/download-artifact@v4
38
+ with: {name: dist, path: dist}
39
+ - name: Publish
40
+ uses: pypa/gh-action-pypi-publish@v1.14.2
@@ -0,0 +1,160 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+ docs/build/
72
+
73
+ # PyBuilder
74
+ .pybuilder/
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ Pipfile.lock
89
+
90
+ # poetry
91
+ poetry.lock
92
+
93
+ # pdm
94
+ .pdm.toml
95
+
96
+ # PEP 582
97
+ __pypackages__/
98
+
99
+ # Celery stuff
100
+ celerybeat-schedule
101
+ celerybeat.pid
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .dmypy.json
128
+ dmypy.json
129
+
130
+ # Pyre type checker
131
+ .pyre/
132
+
133
+ # pytype static type analyzer
134
+ .pytype/
135
+
136
+ # Cython debug symbols
137
+ cython_debug/
138
+
139
+ # IDEs
140
+ .vscode/
141
+ .idea/
142
+ *.swp
143
+ *.swo
144
+ *~
145
+
146
+ # OS
147
+ .DS_Store
148
+ Thumbs.db
149
+
150
+ # Project specific
151
+ *.db
152
+ *.sqlite
153
+ benchmark_results/
154
+ cache/
155
+ logs/
156
+ temp/
157
+ optimization_results.db
158
+ package_maximizer.log
159
+ *.optimized.Dockerfile
160
+ optimal_modules.sh
@@ -0,0 +1,50 @@
1
+ FROM python:3.12-slim
2
+
3
+ LABEL maintainer="Package Maximizer Team <team@package-maximizer.dev>"
4
+ LABEL description="Контейнер для Package Maximizer"
5
+
6
+ # Установка системных зависимостей
7
+ RUN apt-get update && apt-get install -y \
8
+ gcc g++ \
9
+ libffi-dev \
10
+ libssl-dev \
11
+ pkg-config \
12
+ curl \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ # Создание пользователя приложения
16
+ RUN useradd -m -u 1000 pmuser && \
17
+ mkdir -p /app /data /cache && \
18
+ chown -R pmuser:pmuser /app /data /cache
19
+
20
+ WORKDIR /app
21
+
22
+ # Копирование файлов требований
23
+ COPY requirements.txt .
24
+
25
+ # Установка Python зависимостей
26
+ RUN pip install --no-cache-dir -r requirements.txt
27
+
28
+ # Копирование исходного кода
29
+ COPY --chown=pmuser:pmuser . .
30
+
31
+ # Установка пакета
32
+ RUN pip install -e .
33
+
34
+ # Переключение на пользователя приложения
35
+ USER pmuser
36
+
37
+ EXPOSE 5000
38
+
39
+ # Переменные окружения
40
+ ENV FLASK_APP=package_maximizer.web.app
41
+ ENV FLASK_ENV=production
42
+ ENV PACKAGE_MAXIMIZER_CACHE_DIR=/cache
43
+ ENV PACKAGE_MAXIMIZER_DATA_DIR=/data
44
+
45
+ # Проверка здоровья
46
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
47
+ CMD curl -f http://localhost:5000/ || exit 1
48
+
49
+ # Команда по умолчанию
50
+ CMD ["python", "-m", "package_maximizer.web.app"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dominicusin (Domini Montessori)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the SOFTWARE.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,48 @@
1
+ .PHONY: help install test lint format clean build docker run
2
+
3
+ help: ## Показать это сообщение помощи
4
+ @echo "Доступные команды:"
5
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
6
+
7
+ install: ## Установить зависимости
8
+ pip install -r requirements.txt
9
+ pip install -e .
10
+
11
+ install-dev: ## Установить зависимости для разработки
12
+ pip install -r requirements.txt
13
+ pip install -e ".[dev,all,web]"
14
+
15
+ test: ## Запустить тесты
16
+ pytest tests/ -v --cov=package_maximizer --cov-report=html --cov-report=term
17
+
18
+ lint: ## Проверить код линтерами
19
+ flake8 package_maximizer/ tests/
20
+ mypy package_maximizer/ --ignore-missing-imports
21
+
22
+ format: ## Отформатировать код
23
+ black package_maximizer/ tests/
24
+ isort package_maximizer/ tests/
25
+
26
+ clean: ## Очистить временные файлы
27
+ find . -type f -name "*.pyc" -delete
28
+ find . -type d -name "__pycache__" -delete
29
+ rm -rf build/ dist/ *.egg-info/
30
+ rm -rf .coverage htmlcov/
31
+ rm -rf .pytest_cache/
32
+
33
+ build: ## Собрать пакет
34
+ python -m build
35
+
36
+ docker-build: ## Собрать Docker образ
37
+ docker build -t package-maximizer:latest .
38
+
39
+ docker-run: ## Запустить в Docker
40
+ docker run -p 5000:5000 package-maximizer:latest
41
+
42
+ run-web: ## Запустить веб-интерфейс
43
+ python -m package_maximizer.web.app
44
+
45
+ init-config: ## Создать файл конфигурации по умолчанию
46
+ package-maximizer init-config
47
+
48
+ all: lint test build ## Выполнить все проверки и сборку
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: package-maximizer
3
+ Version: 0.0.0
4
+ Summary: Модульная система для максимизации непротиворечивого множества пакетов
5
+ Author-email: Package Maximizer Team <team@package-maximizer.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/package-maximizer/package-maximizer
8
+ Project-URL: Documentation, https://package-maximizer.readthedocs.io/
9
+ Project-URL: Repository, https://github.com/package-maximizer/package-maximizer.git
10
+ Project-URL: Bug Tracker, https://github.com/package-maximizer/package-maximizer/issues
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Topic :: System :: Software Distribution
15
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: click>=8.0.0
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: numpy>=1.20.0
28
+ Requires-Dist: pandas>=1.3.0
29
+ Requires-Dist: matplotlib>=3.5.0
30
+ Requires-Dist: seaborn>=0.11.0
31
+ Requires-Dist: psutil>=5.8.0
32
+ Requires-Dist: requests>=2.25.0
33
+ Provides-Extra: web
34
+ Requires-Dist: flask>=2.0.0; extra == "web"
35
+ Requires-Dist: werkzeug<4,>=2.0; extra == "web"
36
+ Requires-Dist: gunicorn>=20.0.0; extra == "web"
37
+ Provides-Extra: solvers
38
+ Requires-Dist: z3-solver>=4.8.0; extra == "solvers"
39
+ Requires-Dist: pulp>=2.5.0; extra == "solvers"
40
+ Requires-Dist: ortools>=9.0.0; extra == "solvers"
41
+ Provides-Extra: all
42
+ Requires-Dist: package-maximizer[solvers,web]; extra == "all"
43
+ Provides-Extra: dev
44
+ Requires-Dist: pytest>=6.2.0; extra == "dev"
45
+ Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
46
+ Requires-Dist: black>=21.0.0; extra == "dev"
47
+ Requires-Dist: flake8>=4.0.0; extra == "dev"
48
+ Requires-Dist: mypy>=0.910; extra == "dev"
49
+ Requires-Dist: isort>=5.0.0; extra == "dev"
50
+ Requires-Dist: pre-commit>=2.15.0; extra == "dev"
51
+ Dynamic: license-file
52
+
53
+ # Package Maximizer 📦🔍
54
+
55
+ [![CI/CD](https://github.com/dominicusin/package-maximizer/workflows/Package%20Maximizer%20CI/CD/badge.svg)](https://github.com/dominicusin/package-maximizer/actions)
56
+ [![codecov](https://codecov.io/gh/dominicusin/package-maximizer/branch/main/graph/badge.svg)](https://codecov.io/gh/dominicusin/package-maximizer)
57
+ [![PyPI version](https://badge.fury.io/py/package-maximizer.svg)](https://badge.fury.io/py/package-maximizer)
58
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
59
+
60
+ Модульная система для решения задачи максимизации непротиворечивого множества пакетов с использованием различных SAT/ILP/SMT солверов для множественных пакетных менеджеров.
61
+
62
+ ## 🚀 Возможности
63
+
64
+ - **Поддержка множественных пакетных менеджеров**: pacman, apt, dnf, zypper, brew, Spack и другие
65
+ - **Различные солверы**: Z3, PuLP, OR-Tools, MaxSAT, MiniSat
66
+ - **Параллельное решение**: одновременный запуск нескольких солверов
67
+ - **Веб-интерфейс**: интуитивный веб-интерфейс с визуализацией
68
+ - **CLI инструменты**: мощный командный интерфейс
69
+ - **Бенчмаркинг**: сравнение производительности солверов
70
+ - **Модульная архитектура**: легко расширяемая система
71
+
72
+ ## 📋 Требования
73
+
74
+ - Python 3.8+
75
+ - Один или несколько поддерживаемых солверов
76
+
77
+ ## 🔧 Установка
78
+ ```bash
79
+ # Из исходного кода
80
+ git clone https://github.com/dominicusin/package-maximizer.git
81
+ cd package-maximizer
82
+ pip install -e ".[all]"
83
+
84
+ ---
85
+
86
+ 🔄 **Mirrors:** [![GitLab](https://img.shields.io/badge/GitLab-dominicusin-orange?logo=gitlab)](https://gitlab.com/dominicusin/package-maximizer) · GitHub is canonical.
87
+
88
+ ## 📊 Solvers & Benchmarks
89
+
90
+ | Solver | Тип | Установка | Статус |
91
+ |---|---|---|---|
92
+ | **Z3** | SMT | `pip install package-maximizer[solvers]` (z3-solver) | ✅ основной |
93
+ | **PuLP** | ILP/MIP | входит в `[solvers]` | ✅ основной |
94
+ | **OR-Tools** | CP-SAT | входит в `[solvers]` | ✅ опционально |
95
+ | **MaxSAT / MiniSat** | SAT | через `[all]` / python-sat | 🔬 экспериментально |
96
+
97
+ Запуск бенчмарков: `python -m package_maximizer.bench --solvers z3,pulp --packages 500`
98
+ (сравнение времени решения и качества множества на синтетических зависимостных графах).
@@ -0,0 +1,46 @@
1
+ # Package Maximizer 📦🔍
2
+
3
+ [![CI/CD](https://github.com/dominicusin/package-maximizer/workflows/Package%20Maximizer%20CI/CD/badge.svg)](https://github.com/dominicusin/package-maximizer/actions)
4
+ [![codecov](https://codecov.io/gh/dominicusin/package-maximizer/branch/main/graph/badge.svg)](https://codecov.io/gh/dominicusin/package-maximizer)
5
+ [![PyPI version](https://badge.fury.io/py/package-maximizer.svg)](https://badge.fury.io/py/package-maximizer)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ Модульная система для решения задачи максимизации непротиворечивого множества пакетов с использованием различных SAT/ILP/SMT солверов для множественных пакетных менеджеров.
9
+
10
+ ## 🚀 Возможности
11
+
12
+ - **Поддержка множественных пакетных менеджеров**: pacman, apt, dnf, zypper, brew, Spack и другие
13
+ - **Различные солверы**: Z3, PuLP, OR-Tools, MaxSAT, MiniSat
14
+ - **Параллельное решение**: одновременный запуск нескольких солверов
15
+ - **Веб-интерфейс**: интуитивный веб-интерфейс с визуализацией
16
+ - **CLI инструменты**: мощный командный интерфейс
17
+ - **Бенчмаркинг**: сравнение производительности солверов
18
+ - **Модульная архитектура**: легко расширяемая система
19
+
20
+ ## 📋 Требования
21
+
22
+ - Python 3.8+
23
+ - Один или несколько поддерживаемых солверов
24
+
25
+ ## 🔧 Установка
26
+ ```bash
27
+ # Из исходного кода
28
+ git clone https://github.com/dominicusin/package-maximizer.git
29
+ cd package-maximizer
30
+ pip install -e ".[all]"
31
+
32
+ ---
33
+
34
+ 🔄 **Mirrors:** [![GitLab](https://img.shields.io/badge/GitLab-dominicusin-orange?logo=gitlab)](https://gitlab.com/dominicusin/package-maximizer) · GitHub is canonical.
35
+
36
+ ## 📊 Solvers & Benchmarks
37
+
38
+ | Solver | Тип | Установка | Статус |
39
+ |---|---|---|---|
40
+ | **Z3** | SMT | `pip install package-maximizer[solvers]` (z3-solver) | ✅ основной |
41
+ | **PuLP** | ILP/MIP | входит в `[solvers]` | ✅ основной |
42
+ | **OR-Tools** | CP-SAT | входит в `[solvers]` | ✅ опционально |
43
+ | **MaxSAT / MiniSat** | SAT | через `[all]` / python-sat | 🔬 экспериментально |
44
+
45
+ Запуск бенчмарков: `python -m package_maximizer.bench --solvers z3,pulp --packages 500`
46
+ (сравнение времени решения и качества множества на синтетических зависимостных графах).
@@ -0,0 +1,29 @@
1
+ """
2
+ Package Maximizer - Модульная система для максимизации пакетов
3
+
4
+ Система для решения задачи максимизации непротиворечивого множества пакетов
5
+ с использованием различных SAT/ILP/SMT солверов.
6
+ """
7
+
8
+ __version__ = "0.1.0"
9
+ __author__ = "Package Maximizer Team"
10
+ __email__ = "team@package-maximizer.dev"
11
+ __license__ = "MIT"
12
+
13
+ # Enums
14
+ from .core.enums import PackageManagerType, SolverType
15
+ from .core.interfaces import ConstraintSolver, PackageParser, ResultAnalyzer
16
+ from .core.maximizer import PackageMaximizer
17
+ from .core.package import Package, PackageConstraint
18
+
19
+ __all__ = [
20
+ "Package",
21
+ "PackageConstraint",
22
+ "PackageMaximizer",
23
+ "PackageParser",
24
+ "ConstraintSolver",
25
+ "ResultAnalyzer",
26
+ "PackageManagerType",
27
+ "SolverType",
28
+ "__version__",
29
+ ]
@@ -0,0 +1,17 @@
1
+ """Основные компоненты Package Maximizer"""
2
+
3
+ from .enums import PackageManagerType, SolverType
4
+ from .interfaces import ConstraintSolver, PackageParser, ResultAnalyzer
5
+ from .maximizer import PackageMaximizer
6
+ from .package import Package, PackageConstraint
7
+
8
+ __all__ = [
9
+ "Package",
10
+ "PackageConstraint",
11
+ "PackageMaximizer",
12
+ "PackageParser",
13
+ "ConstraintSolver",
14
+ "ResultAnalyzer",
15
+ "PackageManagerType",
16
+ "SolverType",
17
+ ]
@@ -0,0 +1,33 @@
1
+ """Типы пакетных менеджеров и солверов."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class PackageManagerType(Enum):
7
+ APT = "apt"
8
+ PACMAN = "pacman"
9
+ DNF = "dnf"
10
+ ZYPPER = "zypper"
11
+ BREW = "brew"
12
+ SPACK = "spack"
13
+ FLATPAK = "flatpak"
14
+ SNAP = "snap"
15
+ NIX = "nix"
16
+ GUIX = "guix"
17
+ PORTAGE = "portage"
18
+ XBS = "xbps"
19
+
20
+
21
+ class SolverType(Enum):
22
+ Z3 = "z3"
23
+ PULP = "pulp"
24
+ ORTOOLS = "ortools"
25
+ MAXSAT = "maxsat"
26
+ MINISAT = "minisat"
27
+
28
+
29
+ class PackageStatus(Enum):
30
+ INSTALLED = "installed"
31
+ MISSING = "missing"
32
+ CONFLICTED = "conflicted"
33
+ CANDIDATE = "candidate"
@@ -0,0 +1,33 @@
1
+ """Абстрактные интерфейсы солверов, парсеров и анализаторов."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import TYPE_CHECKING, Iterable
7
+
8
+ if TYPE_CHECKING:
9
+ from .package import Package
10
+
11
+
12
+ class ConstraintSolver(ABC):
13
+ """Решатель задачи максимизации непротиворечивого множества пакетов."""
14
+
15
+ @abstractmethod
16
+ def solve(self, packages: Iterable[Package]) -> list[str]:
17
+ """Возвращает список имён пакетов, образующих максимальное согласованное множество."""
18
+
19
+
20
+ class PackageParser(ABC):
21
+ """Парсер вывода пакетного менеджера."""
22
+
23
+ @abstractmethod
24
+ def parse(self, raw: str) -> list[Package]:
25
+ """Разбирает текстовый вывод менеджера в список Package."""
26
+
27
+
28
+ class ResultAnalyzer(ABC):
29
+ """Анализатор результата работы солвера."""
30
+
31
+ @abstractmethod
32
+ def analyze(self, installed: Iterable[str], proposed: Iterable[str]) -> dict:
33
+ """Сравнивает установленный набор с предложенным решением."""
@@ -0,0 +1,58 @@
1
+ """Ядро: максимизация непротиворечивого множества пакетов."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import itertools
6
+ from typing import Iterable, Sequence
7
+
8
+ from .enums import PackageManagerType, SolverType
9
+ from .package import Package, PackageConstraint
10
+
11
+
12
+ class PackageMaximizer:
13
+ """Строит максимальное непротиворечивое подмножество пакетов.
14
+
15
+ Базовая реализация (без внешних солверов): жадный обход с проверкой
16
+ конфликтов и зависимостей. Внешние SAT/ILP-солверы подключаются
17
+ через :mod:`package_maximizer.solvers`.
18
+ """
19
+
20
+ def __init__(
21
+ self,
22
+ manager: PackageManagerType | str = PackageManagerType.APT,
23
+ solver: SolverType | str = SolverType.PULP,
24
+ ) -> None:
25
+ self.manager = (
26
+ manager if isinstance(manager, PackageManagerType) else PackageManagerType(manager)
27
+ )
28
+ self.solver = solver if isinstance(solver, SolverType) else SolverType(solver)
29
+
30
+ def maximize(self, packages: Sequence[Package]) -> list[Package]:
31
+ """Возвращает максимальное непротиворечивое подмножество."""
32
+ chosen: list[Package] = []
33
+ chosen_names: set[str] = set()
34
+ blocked: set[str] = set()
35
+
36
+ for pkg in packages:
37
+ if pkg.name in chosen_names or pkg.name in blocked:
38
+ continue
39
+ if any(c in blocked for c in pkg.conflicts):
40
+ continue
41
+ chosen.append(pkg)
42
+ chosen_names.add(pkg.name)
43
+ blocked.update(pkg.conflicts)
44
+ return chosen
45
+
46
+ def check_constraints(
47
+ self, packages: Iterable[Package], constraints: Iterable[PackageConstraint]
48
+ ) -> dict[str, bool]:
49
+ """Проверяет выполнение ограничений для набора пакетов."""
50
+ versions = {p.name: p.version for p in packages}
51
+ return {
52
+ c.package: c.satisfied_by(versions.get(c.package, ""))
53
+ for c in constraints
54
+ }
55
+
56
+ @staticmethod
57
+ def from_names(names: Iterable[str]) -> list[Package]:
58
+ return [Package(name=n, status="candidate") for n in names]
@@ -0,0 +1,41 @@
1
+ """Модель пакета и его ограничения."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+
8
+ @dataclass
9
+ class Package:
10
+ name: str
11
+ version: str = ""
12
+ status: str = "candidate"
13
+ depends: list = field(default_factory=list)
14
+ conflicts: list = field(default_factory=list)
15
+
16
+ def __str__(self) -> str:
17
+ v = f" {self.version}" if self.version else ""
18
+ return f"{self.name}{v}"
19
+
20
+
21
+ @dataclass
22
+ class PackageConstraint:
23
+ package: str
24
+ op: str = ">="
25
+ version: str = ""
26
+
27
+ def satisfied_by(self, other_version: str) -> bool:
28
+ if not self.version or not other_version:
29
+ return True
30
+
31
+ def key(v):
32
+ return [int(x) for x in v.split(".") if x.isdigit()]
33
+
34
+ a, b = key(other_version), key(self.version)
35
+ return {
36
+ ">=": a >= b,
37
+ "<=": a <= b,
38
+ "==": a == b,
39
+ ">": a > b,
40
+ "<": a < b,
41
+ }.get(self.op, True)
@@ -0,0 +1,3 @@
1
+ from .app import app, run
2
+
3
+ __all__ = ["app", "run"]
@@ -0,0 +1,43 @@
1
+ """Минимальный веб-интерфейс Package Maximizer (Flask)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from flask import Flask, jsonify, request
6
+
7
+ from ..core.enums import PackageManagerType, SolverType
8
+ from ..core.maximizer import PackageMaximizer
9
+ from ..core.package import Package
10
+
11
+ app = Flask(__name__)
12
+
13
+
14
+ @app.get("/api/health")
15
+ def health():
16
+ return jsonify(status="ok")
17
+
18
+
19
+ @app.get("/api/maximize")
20
+ def maximize():
21
+ """GET /api/maximize?packages=vim,nano&manager=apt&solver=pulp"""
22
+ raw = request.args.get("packages", "")
23
+ names = [n.strip() for n in raw.split(",") if n.strip()]
24
+ if not names:
25
+ return jsonify(error="параметр 'packages' обязателен"), 400
26
+ try:
27
+ manager = PackageManagerType(request.args.get("manager", "apt"))
28
+ solver = SolverType(request.args.get("solver", "pulp"))
29
+ except ValueError as e:
30
+ return jsonify(error=str(e)), 400
31
+
32
+ engine = PackageMaximizer(manager=manager, solver=solver)
33
+ chosen = engine.maximize(PackageMaximizer.from_names(names))
34
+ return jsonify(
35
+ manager=manager.value,
36
+ solver=solver.value,
37
+ input=names,
38
+ maximized=[p.name for p in chosen],
39
+ )
40
+
41
+
42
+ def run(host: str = "127.0.0.1", port: int = 5000) -> None:
43
+ app.run(host=host, port=port)
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: package-maximizer
3
+ Version: 0.0.0
4
+ Summary: Модульная система для максимизации непротиворечивого множества пакетов
5
+ Author-email: Package Maximizer Team <team@package-maximizer.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/package-maximizer/package-maximizer
8
+ Project-URL: Documentation, https://package-maximizer.readthedocs.io/
9
+ Project-URL: Repository, https://github.com/package-maximizer/package-maximizer.git
10
+ Project-URL: Bug Tracker, https://github.com/package-maximizer/package-maximizer/issues
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Topic :: System :: Software Distribution
15
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: click>=8.0.0
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: numpy>=1.20.0
28
+ Requires-Dist: pandas>=1.3.0
29
+ Requires-Dist: matplotlib>=3.5.0
30
+ Requires-Dist: seaborn>=0.11.0
31
+ Requires-Dist: psutil>=5.8.0
32
+ Requires-Dist: requests>=2.25.0
33
+ Provides-Extra: web
34
+ Requires-Dist: flask>=2.0.0; extra == "web"
35
+ Requires-Dist: werkzeug<4,>=2.0; extra == "web"
36
+ Requires-Dist: gunicorn>=20.0.0; extra == "web"
37
+ Provides-Extra: solvers
38
+ Requires-Dist: z3-solver>=4.8.0; extra == "solvers"
39
+ Requires-Dist: pulp>=2.5.0; extra == "solvers"
40
+ Requires-Dist: ortools>=9.0.0; extra == "solvers"
41
+ Provides-Extra: all
42
+ Requires-Dist: package-maximizer[solvers,web]; extra == "all"
43
+ Provides-Extra: dev
44
+ Requires-Dist: pytest>=6.2.0; extra == "dev"
45
+ Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
46
+ Requires-Dist: black>=21.0.0; extra == "dev"
47
+ Requires-Dist: flake8>=4.0.0; extra == "dev"
48
+ Requires-Dist: mypy>=0.910; extra == "dev"
49
+ Requires-Dist: isort>=5.0.0; extra == "dev"
50
+ Requires-Dist: pre-commit>=2.15.0; extra == "dev"
51
+ Dynamic: license-file
52
+
53
+ # Package Maximizer 📦🔍
54
+
55
+ [![CI/CD](https://github.com/dominicusin/package-maximizer/workflows/Package%20Maximizer%20CI/CD/badge.svg)](https://github.com/dominicusin/package-maximizer/actions)
56
+ [![codecov](https://codecov.io/gh/dominicusin/package-maximizer/branch/main/graph/badge.svg)](https://codecov.io/gh/dominicusin/package-maximizer)
57
+ [![PyPI version](https://badge.fury.io/py/package-maximizer.svg)](https://badge.fury.io/py/package-maximizer)
58
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
59
+
60
+ Модульная система для решения задачи максимизации непротиворечивого множества пакетов с использованием различных SAT/ILP/SMT солверов для множественных пакетных менеджеров.
61
+
62
+ ## 🚀 Возможности
63
+
64
+ - **Поддержка множественных пакетных менеджеров**: pacman, apt, dnf, zypper, brew, Spack и другие
65
+ - **Различные солверы**: Z3, PuLP, OR-Tools, MaxSAT, MiniSat
66
+ - **Параллельное решение**: одновременный запуск нескольких солверов
67
+ - **Веб-интерфейс**: интуитивный веб-интерфейс с визуализацией
68
+ - **CLI инструменты**: мощный командный интерфейс
69
+ - **Бенчмаркинг**: сравнение производительности солверов
70
+ - **Модульная архитектура**: легко расширяемая система
71
+
72
+ ## 📋 Требования
73
+
74
+ - Python 3.8+
75
+ - Один или несколько поддерживаемых солверов
76
+
77
+ ## 🔧 Установка
78
+ ```bash
79
+ # Из исходного кода
80
+ git clone https://github.com/dominicusin/package-maximizer.git
81
+ cd package-maximizer
82
+ pip install -e ".[all]"
83
+
84
+ ---
85
+
86
+ 🔄 **Mirrors:** [![GitLab](https://img.shields.io/badge/GitLab-dominicusin-orange?logo=gitlab)](https://gitlab.com/dominicusin/package-maximizer) · GitHub is canonical.
87
+
88
+ ## 📊 Solvers & Benchmarks
89
+
90
+ | Solver | Тип | Установка | Статус |
91
+ |---|---|---|---|
92
+ | **Z3** | SMT | `pip install package-maximizer[solvers]` (z3-solver) | ✅ основной |
93
+ | **PuLP** | ILP/MIP | входит в `[solvers]` | ✅ основной |
94
+ | **OR-Tools** | CP-SAT | входит в `[solvers]` | ✅ опционально |
95
+ | **MaxSAT / MiniSat** | SAT | через `[all]` / python-sat | 🔬 экспериментально |
96
+
97
+ Запуск бенчмарков: `python -m package_maximizer.bench --solvers z3,pulp --packages 500`
98
+ (сравнение времени решения и качества множества на синтетических зависимостных графах).
@@ -0,0 +1,33 @@
1
+ .gitignore
2
+ Dockerfile
3
+ LICENSE
4
+ Makefile
5
+ README.md
6
+ pyproject.toml
7
+ requirements.txt
8
+ .github/ISSUE_TEMPLATE/bug_report.md
9
+ .github/ISSUE_TEMPLATE/feature_request.md
10
+ .github/workflows/ci.yml
11
+ .github/workflows/publish.yml
12
+ package_maximizer/__init__.py
13
+ package_maximizer.egg-info/PKG-INFO
14
+ package_maximizer.egg-info/SOURCES.txt
15
+ package_maximizer.egg-info/dependency_links.txt
16
+ package_maximizer.egg-info/entry_points.txt
17
+ package_maximizer.egg-info/requires.txt
18
+ package_maximizer.egg-info/top_level.txt
19
+ package_maximizer/analyzers/__init__.py
20
+ package_maximizer/cli/__init__.py
21
+ package_maximizer/config/__init__.py
22
+ package_maximizer/core/__init__.py
23
+ package_maximizer/core/enums.py
24
+ package_maximizer/core/interfaces.py
25
+ package_maximizer/core/maximizer.py
26
+ package_maximizer/core/package.py
27
+ package_maximizer/parsers/__init__.py
28
+ package_maximizer/solvers/__init__.py
29
+ package_maximizer/utils/__init__.py
30
+ package_maximizer/web/__init__.py
31
+ package_maximizer/web/app.py
32
+ tests/__init__.py
33
+ tests/test_basic.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ package-maximizer = package_maximizer.cli.main:cli
3
+ pm-web = package_maximizer.web.app:run_app
@@ -0,0 +1,30 @@
1
+ click>=8.0.0
2
+ pyyaml>=6.0
3
+ numpy>=1.20.0
4
+ pandas>=1.3.0
5
+ matplotlib>=3.5.0
6
+ seaborn>=0.11.0
7
+ psutil>=5.8.0
8
+ requests>=2.25.0
9
+
10
+ [all]
11
+ package-maximizer[solvers,web]
12
+
13
+ [dev]
14
+ pytest>=6.2.0
15
+ pytest-cov>=3.0.0
16
+ black>=21.0.0
17
+ flake8>=4.0.0
18
+ mypy>=0.910
19
+ isort>=5.0.0
20
+ pre-commit>=2.15.0
21
+
22
+ [solvers]
23
+ z3-solver>=4.8.0
24
+ pulp>=2.5.0
25
+ ortools>=9.0.0
26
+
27
+ [web]
28
+ flask>=2.0.0
29
+ werkzeug<4,>=2.0
30
+ gunicorn>=20.0.0
@@ -0,0 +1 @@
1
+ package_maximizer
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "package-maximizer"
7
+ description = "Модульная система для максимизации непротиворечивого множества пакетов"
8
+ authors = [{name = "Package Maximizer Team", email = "team@package-maximizer.dev"}]
9
+ license = {text = "MIT"}
10
+ readme = "README.md"
11
+ requires-python = ">=3.8"
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Developers",
15
+ "Intended Audience :: System Administrators",
16
+ "Topic :: System :: Software Distribution",
17
+ "Topic :: Scientific/Engineering :: Mathematics",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ ]
25
+ dynamic = ["version"]
26
+ dependencies = [
27
+ "click>=8.0.0",
28
+ "pyyaml>=6.0",
29
+ "numpy>=1.20.0",
30
+ "pandas>=1.3.0",
31
+ "matplotlib>=3.5.0",
32
+ "seaborn>=0.11.0",
33
+ "psutil>=5.8.0",
34
+ "requests>=2.25.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ web = [
39
+ "flask>=2.0.0",
40
+ "werkzeug>=2.0,<4",
41
+ "gunicorn>=20.0.0",
42
+ ]
43
+ solvers = [
44
+ "z3-solver>=4.8.0",
45
+ "pulp>=2.5.0",
46
+ "ortools>=9.0.0",
47
+ ]
48
+ all = [
49
+ "package-maximizer[web,solvers]",
50
+ ]
51
+ dev = [
52
+ "pytest>=6.2.0",
53
+ "pytest-cov>=3.0.0",
54
+ "black>=21.0.0",
55
+ "flake8>=4.0.0",
56
+ "mypy>=0.910",
57
+ "isort>=5.0.0",
58
+ "pre-commit>=2.15.0",
59
+ ]
60
+
61
+ [project.scripts]
62
+ package-maximizer = "package_maximizer.cli.main:cli"
63
+ pm-web = "package_maximizer.web.app:run_app"
64
+
65
+ [project.urls]
66
+ Homepage = "https://github.com/package-maximizer/package-maximizer"
67
+ Documentation = "https://package-maximizer.readthedocs.io/"
68
+ Repository = "https://github.com/package-maximizer/package-maximizer.git"
69
+ "Bug Tracker" = "https://github.com/package-maximizer/package-maximizer/issues"
@@ -0,0 +1,34 @@
1
+ # Основные зависимости
2
+ click>=8.0.0
3
+ pyyaml>=6.0
4
+ numpy>=1.20.0
5
+ pandas>=1.3.0
6
+ matplotlib>=3.5.0
7
+ seaborn>=0.11.0
8
+ psutil>=5.8.0
9
+
10
+ # Веб-интерфейс
11
+ flask>=2.0.0
12
+ werkzeug>=2.0,<4
13
+
14
+ # Солверы (опционально)
15
+ z3-solver>=4.8.0
16
+ pulp>=2.5.0
17
+ ortools>=9.0.0
18
+
19
+ # Для работы с различными пакетными менеджерами
20
+ requests>=2.25.0
21
+ lxml>=4.6.0
22
+ beautifulsoup4>=4.9.0
23
+
24
+ # Тестирование
25
+ pytest>=6.2.0
26
+ pytest-cov>=3.0.0
27
+
28
+ # Разработка
29
+ black>=21.0.0
30
+ flake8>=4.0.0
31
+ mypy>=0.910
32
+ fonttools>=4.38.0 ; python_version >= "3.9" # Snyk: transitive vuln fix (4.61 needs py3.9)
33
+ urllib3>=2.0.7 ; python_version >= "3.9" # Snyk: transitive vuln fix (2.6 needs py3.9)
34
+ urllib3>=1.26.18,<2 ; python_version < "3.9" # legacy branch
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,26 @@
1
+ """Базовые тесты для проверки работоспособности"""
2
+
3
+
4
+ def test_import():
5
+ """Тест импорта основных модулей"""
6
+ try:
7
+ import package_maximizer
8
+
9
+ assert hasattr(package_maximizer, "__version__")
10
+ assert package_maximizer.__version__ == "0.1.0"
11
+ except ImportError:
12
+ assert False, "Не удалось импортировать package_maximizer"
13
+
14
+
15
+ def test_basic_functionality():
16
+ """Тест базовой функциональности"""
17
+ # Пока простая проверка
18
+ assert 1 + 1 == 2
19
+
20
+
21
+ def test_version():
22
+ """Тест версии пакета"""
23
+ from package_maximizer import __version__
24
+
25
+ assert __version__ is not None
26
+ assert isinstance(__version__, str)