diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ba1c6b8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" diff --git a/.github/workflows/publish_autoroot.yml b/.github/workflows/publish_autoroot.yml new file mode 100644 index 0000000..8c165c9 --- /dev/null +++ b/.github/workflows/publish_autoroot.yml @@ -0,0 +1,37 @@ +name: build + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.x" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build package + run: | + cd autoroot + python -m build + + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + packages_dir: autoroot/dist/ diff --git a/.github/workflows/publish_autorootcwd.yml b/.github/workflows/publish_autorootcwd.yml new file mode 100644 index 0000000..992ae73 --- /dev/null +++ b/.github/workflows/publish_autorootcwd.yml @@ -0,0 +1,37 @@ +name: build + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.x" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build package + run: | + cd autorootcwd + python -m build + + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + packages_dir: autorootcwd/dist/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6a8a9b8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,74 @@ +name: tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + run_tests: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + python-version: ["3.7", "3.8", "3.9", "3.10"] + + timeout-minutes: 10 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: List dependencies + run: | + python -m pip list + + - name: Run pytest + run: | + pytest -v + + # upload code coverate report + code-coverage: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: "3.10" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run tests and collect coverage + run: pytest --cov pyrootutils + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + + # check code formatting + pre-commit: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: pre-commit/action@v2.0.3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb31eb4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +# 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/ +pip-wheel-metadata/ +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/ + +# 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 +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.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 + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__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/ + +# IDE +.vscode +.idea diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..6730979 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,53 @@ +default_language_version: + python: python3 + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + # list of supported hooks: https://pre-commit.com/hooks.html + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-docstring-first + - id: check-yaml + - id: debug-statements + - id: detect-private-key + - id: check-executables-have-shebangs + - id: check-toml + - id: check-case-conflict + - id: check-added-large-files + + # python code formatting + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + args: [--line-length, "99"] + + # python import sorting + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + args: ["--profile", "black", "--extra-builtin", "autoroot"] + + # python upgrading syntax to newer version + - repo: https://github.com/asottile/pyupgrade + rev: v2.32.1 + hooks: + - id: pyupgrade + args: [--py37-plus] + + # python check (PEP8), programming errors and code complexity + - repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + args: ["--ignore", "E501,F401,F841,W504", "--exclude", "logs/*,data/*"] + + # python security linter + - repo: https://github.com/PyCQA/bandit + rev: "1.7.1" + hooks: + - id: bandit + args: ["-s", "B101"] diff --git a/.project-root b/.project-root new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE index 5895017..05fcbbf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Lukas +Copyright (c) 2022 Łukasz Zalewski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca3ed5b --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# autoroot + +Automatic project root setup with just one import! + +You just need to create empty ".project-root" file in your project root directory. + +## Installation + +```bash +pip install autoroot +pip install autorootcwd +``` + +## Usage + +```python +import autoroot +``` + +Or: + +```python +import autorootcwd +``` + +That's it! You're done. diff --git a/autoroot/__init__.py b/autoroot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/autoroot/autoroot/__init__.py b/autoroot/autoroot/__init__.py new file mode 100644 index 0000000..dd77fb8 --- /dev/null +++ b/autoroot/autoroot/__init__.py @@ -0,0 +1,26 @@ +import os +import sys +from pathlib import Path + +from pyrootutils import setup_root + +# this line finds the absolute path of the original python script that is being run +startfile = os.path.abspath(sys.argv[0]) + +# if we are in notebook or pytest, just use current working directory +if startfile.endswith("ipykernel_launcher.py") or startfile.endswith("pytest"): + startfile = os.getcwd() + +# convert to Path object +startfile = Path(startfile) + +# this line recursively searches for ".project-root" file +# starting from folder containing the entry python script and going up until it finds it +root = setup_root( + search_from=startfile, + indicator=".project-root", + project_root_env_var=True, + dotenv=True, + pythonpath=True, + cwd=False, +) diff --git a/autoroot/setup.py b/autoroot/setup.py new file mode 100644 index 0000000..f8613ab --- /dev/null +++ b/autoroot/setup.py @@ -0,0 +1,18 @@ +from setuptools import find_packages, setup + +setup( + name="autoroot", + version="1.0.0", + license="MIT", + description="Simple package for easy project root setup", + long_description="", + long_description_content_type="text/markdown", + url="https://github.com/ashleve/autoroot", + author="Łukasz Zalewski", + author_email="lukasz.zalewski.ai@gmail.com", + packages=find_packages(), + python_requires=">=3.7.0", + include_package_data=True, + install_requires=["python-dotenv>=0.20.0", "pyrootutils>=1.0.4"], + tests_require=["pytest"], +) diff --git a/autorootcwd/__init__.py b/autorootcwd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/autorootcwd/autorootcwd/__init__.py b/autorootcwd/autorootcwd/__init__.py new file mode 100644 index 0000000..10e0990 --- /dev/null +++ b/autorootcwd/autorootcwd/__init__.py @@ -0,0 +1,26 @@ +import os +import sys +from pathlib import Path + +from pyrootutils import setup_root + +# this line finds the absolute path of the original python script that is being run +startfile = os.path.abspath(sys.argv[0]) + +# if we are in notebook or pytest, just use current working directory +if startfile.endswith("ipykernel_launcher.py") or startfile.endswith("pytest"): + startfile = os.getcwd() + +# convert to Path object +startfile = Path(startfile) + +# this line recursively searches for ".project-root" file +# starting from folder containing the entry python script and going up until it finds it +root = setup_root( + search_from=startfile, + indicator=".project-root", + project_root_env_var=True, + dotenv=True, + pythonpath=True, + cwd=True, +) diff --git a/autorootcwd/setup.py b/autorootcwd/setup.py new file mode 100644 index 0000000..afe27d3 --- /dev/null +++ b/autorootcwd/setup.py @@ -0,0 +1,18 @@ +from setuptools import find_packages, setup + +setup( + name="autorootcwd", + version="1.0.0", + license="MIT", + description="Simple package for easy project root setup", + long_description="", + long_description_content_type="text/markdown", + url="https://github.com/ashleve/autoroot", + author="Łukasz Zalewski", + author_email="lukasz.zalewski.ai@gmail.com", + packages=find_packages(), + python_requires=">=3.7.0", + include_package_data=True, + install_requires=["python-dotenv>=0.20.0", "pyrootutils>=1.0.4"], + tests_require=["pytest"], +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b4f203d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,24 @@ +[tool.pytest.ini_options] +addopts = [ + "--color=yes", + "--durations=0", + "--strict-markers", + "--doctest-modules", +] +filterwarnings = [ + "ignore::DeprecationWarning", + "ignore::UserWarning", +] +log_cli = "True" +markers = [ + "slow: slow tests", +] +testpaths = "tests/" + +[tool.coverage.report] +exclude_lines = [ + "raise NotImplementedError", + "raise NotImplementedError()", + "pragma: nocover", + "if __name__ == .__main__.:", +] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ebcb61d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +python-dotenv>=0.20.0 +pyrootutils>=1.0.4 +pytest>=7.1.2 +pytest-cov>=3.0.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_autoroot.py b/tests/test_autoroot.py new file mode 100644 index 0000000..fd760cc --- /dev/null +++ b/tests/test_autoroot.py @@ -0,0 +1,5 @@ +from autoroot import autoroot + + +def test_autoroot(): + assert autoroot.root diff --git a/tests/test_autorootcwd.py b/tests/test_autorootcwd.py new file mode 100644 index 0000000..b5c88f5 --- /dev/null +++ b/tests/test_autorootcwd.py @@ -0,0 +1,5 @@ +from autorootcwd import autorootcwd + + +def test_autoroot(): + assert autorootcwd.root