diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..244b924 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,17 @@ + +## Summary + + + +Solve the issue: #___ + +## Quick changelog + +- +- + +## What's new? + + diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..22828c7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,20 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + groups: + github-actions: + patterns: + - "*" + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "deps: " + groups: + pip-dependencies: + patterns: + - "*" \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..483fa2a --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,87 @@ +name: PySATL CI + +on: + push: + branches: + - main + release: + types: [ published ] + pull_request: + +jobs: + build-linux: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ "3.10", "3.11", "3.12" ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + run: pip install poetry==2.1.1 + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Install dependencies with Poetry + run: poetry install --with dev + + - name: Run Ruff lint + run: poetry run ruff check --output-format=github + + - name: Check formatting with Ruff + run: poetry run ruff format --check + + - name: Mypy + run: | + poetry run mypy pysatl_knowledge tests + + - name: Run tests + run: poetry run pytest --random-order + + - name: Tests with Coveralls + if: (runner.os == 'Linux' && matrix.python-version == '3.12') + run: | + poetry run pytest --random-order --cov=pysatl_knowledge --cov-config=.coveragerc + + - name: Coveralls + if: (runner.os == 'Linux' && matrix.python-version == '3.12') + env: + COVERALLS_REPO_TOKEN: ${{ secrets.coverallsToken }} + run: | + # Allow failure for coveralls + poetry run coveralls || true + + - name: Remove poetry.lock before checking for changes + run: rm -f poetry.lock + + - name: Check for repository changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Repository is dirty, changes detected:" + git status + git diff + exit 1 + else + echo "Repository is clean, no changes detected." + fi + + pre-commit: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - uses: pre-commit/action@v3.0.1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37bfd10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,167 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ +/data1/ + +# Local folders and files +execution_time/ +test_distribution/ +cache.json +local_tests.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c135076 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,64 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pycqa/flake8 + rev: "7.1.1" + hooks: + - id: flake8 + additional_dependencies: [Flake8-pyproject] + # stages: [push] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v1.13.0" + hooks: + - id: mypy + exclude: build_helpers + additional_dependencies: + - types-cachetools==5.5.0.20240820 + - types-filelock==3.2.7 + - types-requests==2.32.0.20241016 + - types-tabulate==0.9.0.20240106 + - types-python-dateutil==2.9.0.20241003 + - SQLAlchemy==2.0.36 + # stages: [push] + + - repo: https://github.com/pycqa/isort + rev: "5.13.2" + hooks: + - id: isort + name: isort (python) + # stages: [push] + + - repo: https://github.com/charliermarsh/ruff-pre-commit + # Ruff version. + rev: 'v0.7.4' + hooks: + - id: ruff + - id: ruff-format + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: end-of-file-fixer + exclude: | + (?x)^( + tests/.*| + .*\.svg| + .*\.yml| + .*\.json + )$ + - id: mixed-line-ending + - id: debug-statements + - id: check-ast + - id: trailing-whitespace + exclude: | + (?x)^( + .*\.md + )$ + + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + additional_dependencies: + - tomli diff --git a/README.md b/README.md new file mode 100644 index 0000000..cb84f3f --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +1. Установка: `poetry install` +2. Запустить: `poetry run uvicorn pysatl_knowledge.main:app --reload` +3. Открыть: http://127.0.0.1:8000/doc diff --git a/alembic/env.py b/alembic/env.py new file mode 100644 index 0000000..e69de29 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cf9046a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,98 @@ +[project] +name = "pysatl_knowledge" +version = "0.0.1-alpha" +description = "PySATL module for storing and retrieving computed values." +authors = [ + {name = "PySATL Team", email = "pysatl@yahoo.com"}, +] +license = {text = "MIT"} +readme = "README.md" +requires-python = ">=3.9,<3.13" +dependencies = [ + "fastapi>=0.111.0", + "uvicorn[standard]>=0.30.0", + "sqlalchemy>=2.0.30", + "asyncpg>=0.29.0", + "alembic>=1.13.1", + "pyjwt>=2.8.0", + "passlib[bcrypt]>=1.7.4", + "celery>=5.3.6", + "pydantic>=2.7.0", + "python-dotenv>=1.0.1", + "loguru>=0.7.2", + "httpx>=0.27.0" +] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "pysatl_knowledge" +packages = [ + { include = "pysatl_knowledge" }, +] +package-mode = true + +[tool.poetry.group.dev.dependencies] +markdown = "3.7" +mkdocs = "1.6.1" +mkdocs-material = "9.5.44" +mdx-truly-sane-lists = "1.3" +pymdown-extensions = "10.12" +jinja2 = "3.1.4" +mike = "2.1.3" +isort = "5.13.2" +coveralls = "4.0.1" +pytest = "8.3.3" +pytest-cov = "6.0.0" +pytest-random-order = "1.1.1" +ruff = "0.7.4" +pytest-mock = "3.14.0" +pre-commit = "4.0.1" +mypy = "1.15.0" + +[tool.isort] +line_length = 100 +profile = "black" +# multi_line_output=3 +lines_after_imports=2 +skip_glob = ["**/.env*", "**/env/*", "**/.venv/*", "**/docs/*", "**/user_data/*"] + +[tool.ruff] +line-length = 100 +extend-exclude = [".env", ".venv"] + +[tool.ruff.lint] +extend-select = [ + "C90", "B", "F", "E", "W", "UP", "I", "A", "TID", "YTT", "S", "PTH", "ASYNC", "NPY" +] +extend-ignore = [ + "E241", "E272", "E221", "B007", "B904", "S603", "S607", "S608", "NPY002" +] + +[tool.mypy] +ignore_missing_imports = true +namespace_packages = false +warn_unused_ignores = true + +[[tool.mypy.overrides]] +module = "tests.*" +ignore_errors = true + +[tool.ruff.lint.mccabe] +max-complexity = 12 + +[tool.ruff.lint.isort] +lines-after-imports = 2 + +[tool.flake8] +ignore = ["E121", "E123", "E126", "E24", "E203", "E704", "W503", "W504"] +max-line-length = 100 +max-complexity = 12 +exclude = [".git", "__pycache__", ".eggs", "user_data", ".venv", ".env"] + +[tool.ruff.lint.per-file-ignores] +"tests/**/*.py" = [ + "S101", "S104", "S311", "S105", "S106", "S110" +] diff --git a/pysatl_knowledge/__init__.py b/pysatl_knowledge/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/api/__init__.py b/pysatl_knowledge/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/api/auth.py b/pysatl_knowledge/api/auth.py new file mode 100644 index 0000000..3e6d795 --- /dev/null +++ b/pysatl_knowledge/api/auth.py @@ -0,0 +1,9 @@ +from fastapi import APIRouter + + +router = APIRouter(prefix="/hello", tags=["Hello"]) + + +@router.get("") +async def say_hello(): + return {"message": "Hello World!"} diff --git a/pysatl_knowledge/core/__init__.py b/pysatl_knowledge/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/main.py b/pysatl_knowledge/main.py new file mode 100644 index 0000000..2645d1d --- /dev/null +++ b/pysatl_knowledge/main.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI + +from pysatl_knowledge.api import auth + + +app = FastAPI(title="PySATL-Knowledge") + +app.include_router(auth.router) + + +@app.get("/") +async def root(): + return {"message": "Root endpoint working!"} diff --git a/pysatl_knowledge/models/__init__.py b/pysatl_knowledge/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/notifications/__init__.py b/pysatl_knowledge/notifications/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/repositories/__init__.py b/pysatl_knowledge/repositories/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/schemas/__init__.py b/pysatl_knowledge/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysatl_knowledge/services/__init__.py b/pysatl_knowledge/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29