diff --git a/.bumpversion.toml b/.bumpversion.toml index 51d6fde..e658893 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -20,9 +20,8 @@ setup_hooks = [] pre_commit_hooks = [] post_commit_hooks = [] - [[tool.bumpversion.files]] -filename = "my_project_template/__init__.py" +filename = "src/my_project_template/__init__.py" search = "__version__ = \"{current_version}\"" replace = "__version__ = \"{new_version}\"" @@ -35,3 +34,8 @@ replace = "version = \"{new_version}\"" filename = "api-spec.yaml" search = "version: {current_version}" replace = "version: {new_version}" + +[[tool.bumpversion.files]] +filename = "Makefile" +search = "VERSION := {current_version}" +replace = "VERSION := {new_version}" diff --git a/.dockerignore b/.dockerignore index 06f2cff..073ea4d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ +.git .github .eggs/ build @@ -6,9 +7,9 @@ dist *.egg-info tests venv +.venv __pycache__ -*.pyc *.pyo *.pyd *.output diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 81c7b58..ffafac7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,10 +12,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error + **Expected behavior** A clear and concise description of what you expected to happen. @@ -23,16 +20,5 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - **Additional context** Add any other context about the problem here. diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml deleted file mode 100644 index 3078c19..0000000 --- a/.github/workflows/black.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Format Check - -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: psf/black@stable diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 6bfdc01..729d563 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -1,6 +1,3 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: BDD and Unit Tests on: @@ -10,24 +7,29 @@ on: branches: [ master ] jobs: - build: - + run-tests: + name: python runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - if [ -f requirements-tests.txt ]; then pip install -r requirements-tests.txt; fi - - name: Test with pytest - run: | - pytest - - name: Run BDD Tests - run: | - behave + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: ".python-version" + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + # Install a specific version of uv. + version: "0.8.15" + + - name: Install the project + run: uv sync --locked --group=test + + - name: Run pytests + run: uv run pytest + + - name: Run BDD Tests + run: uv run behave diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..91cd797 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,20 @@ +name: CI +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version-file: ".python-version" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ruff + + # Update output format to enable automatic inline annotations. + - name: Run Ruff + run: ruff check --output-format=github . diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e804c2e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,127 @@ +# Contributing + +Contributions are welcome, and they are greatly appreciated! Every +little bit helps, and credit will always be given. + +You can contribute in many ways: + +## Types of Contributions + +### Report Bugs + +Report bugs at +. + +If you are reporting a bug, please include: + +- Your operating system name and version. +- Any details about your local setup that might be helpful in + troubleshooting. +- Detailed steps to reproduce the bug. + +### Fix Bugs + +Look through the GitHub issues for bugs. Anything tagged with "bug" +and "help wanted" is open to whoever wants to implement it. + +### Implement Features + +Look through the GitHub issues for features. Anything tagged with +"enhancement" and "help wanted" is open to whoever wants to +implement it. + +### Write Documentation + +My Project Template could always use more documentation, whether as part +of the official My Project Template docs, in docstrings, or even on the +web in blog posts, articles, and such. + +### Submit Feedback + +The best way to send feedback is to file an issue at +. + +If you are proposing a feature: + +- Explain in detail how it would work. +- Keep the scope as narrow as possible, to make it easier to implement. +- Remember that this is a volunteer-driven project, and that + contributions are welcome :) + +## Get Started! + +Ready to contribute? Here's how to set up for local development. + +1. Fork the repo on GitHub. + +2. Clone your fork locally: + + ``` shell + $ git clone git@github.com:your_name_here/my_project_template.git + ``` + +3. Install your local copy into a virtual environment. This is how you + set up your fork for local development: + + ``` shell + $ cd my_project_template/ + $ make venv + $ source .venv/bin/activate + $ make install + $ make sync + ``` + +4. Create a branch for local development: + + ``` shell + $ git checkout -b name-of-your-bugfix-or-feature + ``` + + Now you can make your changes locally. + + 5. When done making changes, check that your changes pass + flake8 and the tests, including testing other Python versions with + tox: + + ``` shell + $ pre-commit + $ make test + ``` + +6. Commit your changes and push your branch to GitHub: + + ``` shell + $ git add . + $ git commit -m "Your detailed description of your changes." + $ git push origin name-of-your-bugfix-or-feature + ``` + +7. Submit a pull request through the GitHub website. + +## Pull Request Guidelines + +Before you submit a pull request, check that it meets these guidelines: + +1. The pull request should include tests. +2. If the pull request adds functionality, the docs should be updated. + Put your new functionality into a function with a docstring, and add + the feature to the list in README.rst. +3. The pull request should work for Python 3.6 and higher. + +## Tips + +To run a subset of tests: + +``` shell +$ pytest tests.test_my_project_template +``` + +## Release a new version + +Make sure all your changes are committed. Then run: + +``` shell +$ bump-my-version bump patch -vv # possible: major / minor / patch +$ git push +``` +Maintainer can publish a release, which will submit to PyPi. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index f6216dc..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,126 +0,0 @@ -.. highlight:: shell - -============ -Contributing -============ - -Contributions are welcome, and they are greatly appreciated! Every little bit -helps, and credit will always be given. - -You can contribute in many ways: - -Types of Contributions ----------------------- - -Report Bugs -~~~~~~~~~~~ - -Report bugs at https://github.com/nmdp-bioinformatics/my_project_template/issues. - -If you are reporting a bug, please include: - -* Your operating system name and version. -* Any details about your local setup that might be helpful in troubleshooting. -* Detailed steps to reproduce the bug. - -Fix Bugs -~~~~~~~~ - -Look through the GitHub issues for bugs. Anything tagged with "bug" and "help -wanted" is open to whoever wants to implement it. - -Implement Features -~~~~~~~~~~~~~~~~~~ - -Look through the GitHub issues for features. Anything tagged with "enhancement" -and "help wanted" is open to whoever wants to implement it. - -Write Documentation -~~~~~~~~~~~~~~~~~~~ - -My Project Template could always use more documentation, whether as part of the -official My Project Template docs, in docstrings, or even on the web in blog posts, -articles, and such. - -Submit Feedback -~~~~~~~~~~~~~~~ - -The best way to send feedback is to file an issue at https://github.com/nmdp-bioinformatics/my_project_template/issues. - -If you are proposing a feature: - -* Explain in detail how it would work. -* Keep the scope as narrow as possible, to make it easier to implement. -* Remember that this is a volunteer-driven project, and that contributions - are welcome :) - -Get Started! ------------- - -Ready to contribute? Here's how to set up `my_project_template` for local development. - -1. Fork the `my_project_template` repo on GitHub. -2. Clone your fork locally:: - - $ git clone git@github.com:your_name_here/my_project_template.git - -3. Install your local copy into a virtual environment. This is how you set up your fork for local development:: - - $ cd my_project_template/ - $ make venv - $ source venv/bin/activate - $ make install - $ python setup.py develop - -4. Create a branch for local development:: - - $ git checkout -b name-of-your-bugfix-or-feature - - Now you can make your changes locally. - -5. When you're done making changes, check that your changes pass flake8 and the - tests, including testing other Python versions with tox:: - - $ make lint - $ make test - - -6. Commit your changes and push your branch to GitHub:: - - $ git add . - $ git commit -m "Your detailed description of your changes." - $ git push origin name-of-your-bugfix-or-feature - -7. Submit a pull request through the GitHub website. - -Pull Request Guidelines ------------------------ - -Before you submit a pull request, check that it meets these guidelines: - -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. Put - your new functionality into a function with a docstring, and add the - feature to the list in README.rst. -3. The pull request should work for Python 3.6 and higher. - -Tips ----- - -To run a subset of tests:: - -$ pytest tests.test_my_project_template - - -Deploying ---------- - -A reminder for the maintainers on how to deploy. -Make sure all your changes are committed (including an entry in HISTORY.rst). -Then run:: - -$ bump2version patch # possible: major / minor / patch -$ git push -$ git push --tags - -Travis will then deploy to PyPI if tests pass. diff --git a/Dockerfile b/Dockerfile index 735b1f1..33bdbb1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,49 @@ -FROM python:3.13-slim-trixie - +FROM python:3.13-slim-trixie AS builder LABEL MAINTAINER="Pradeep Bashyal" COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy +ENV UV_PYTHON_PREFERENCE=only-managed + +WORKDIR /app +# Install everything except the package +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --locked --no-install-project --group deploy + +# Sync so that Python version is installed +COPY . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --group deploy && uv build + + +# Final Docker Image +FROM python:3.13-slim-trixie + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + WORKDIR /app +# Copy the Python packages +COPY --from=builder /app/.venv /app/.venv + +COPY --from=builder /app/dist/my_project_template-0.0.1-py3-none-any.whl /tmp/ +RUN python3 -m pip install /tmp/my_project_template-0.0.1-py3-none-any.whl + COPY app.py /app/ COPY api.py /app/ COPY api-spec.yaml /app/ -COPY my_project_template /app/my_project_template +COPY run-app.sh /app/ + +# Put the uv built Python packages in the PATH +ENV PYTHONPATH="/app/.venv/lib/python3.13/site-packages/:" # Sync the project into a new environment, asserting the lockfile is up to date COPY pyproject.toml /app/ COPY uv.lock /app/ -RUN /bin/uv sync --locked --group deploy +RUN uv sync --no-build --no-install-project --locked --group deploy -CMD [".venv/bin/gunicorn" , "--bind", "0.0.0.0:8080", "--worker-tmp-dir", "/dev/shm", "app:app"] +CMD ["/app/run-app.sh"] diff --git a/Makefile b/Makefile index 78e2023..4d950c9 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ lint: ## check style with ruff uv tool run ruff check behave: clean-test ## run the behave tests, generate and serve report - - uv run behave -f allure_behave.formatter:AllureFormatter -o allure_report + uv run behave -f allure_behave.formatter:AllureFormatter -o allure_report allure serve allure_report pytest: clean-test ## run tests quickly with the default Python @@ -86,7 +86,6 @@ docker: docker-build ## build a docker image and run the service sync: clean ## install the package to the active Python's site-packages uv sync --all-groups - pre-commit install install: sync ## Sync pyproject.toml to .venv as well as install tools pre-commit install diff --git a/README.md b/README.md index da092fa..c359969 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ My Project Template How to use the template: -1. Create a template by clicking on the "Use this template" button. Make sure to select all branches +1. Click on the top-right green "Use this template" button. Make sure to select all branches This will create a new repository with the given name e.g. `urban-potato` 2. Clone the repository locally ```shell @@ -14,14 +14,13 @@ How to use the template: 3. Make a virtual environment and activate it, run `make venv` ```shell > make venv - python3 -m venv venv --prompt urban-potato-venv - ===================================================================== - To activate the new virtual environment, execute the following from your shell - source venv/bin/activate - ``` + Using CPython 3.13.7 + Creating virtual environment at: .venv + Activate with: source .venv/bin/activate + ``` 4. Source the virtual environment ```shell - source venv/bin/activate + source .venv/bin/activate ``` 5. Development workflow is driven through `Makefile`. Use `make` to list show all targets. ``` @@ -30,21 +29,23 @@ How to use the template: clean-build remove build artifacts clean-pyc remove Python file artifacts clean-test remove test and coverage artifacts - lint check style with flake8 + lint check style with ruff behave run the behave tests, generate and serve report pytest run tests quickly with the default Python test run all(BDD and unit) tests coverage check code coverage quickly with the default Python dist builds source and wheel package docker-build build a docker image for the service - docker build a docker image for the service - install install the package to the active Python's site-packages + docker build a docker image and run the service + sync install the package to the active Python's site-packages + install Sync pyproject.toml to .venv as well as install tools venv creates a Python3 virtualenv environment in venv activate activate a virtual environment. Run `make venv` before activating. ``` -6. Install all the development dependencies. Will install packages from all `requirements-*.txt` files. +6. Install and sync all the project and development dependencies. ```shell make install + make sync ``` 7. The Gherkin Feature files, step files and pytest files go in `tests` directory: ``` @@ -60,7 +61,7 @@ How to use the template: `-- unit `-- test_my_project_template.py ``` -8. Package Module files go in the `my_project_template` directory. +8. Package Module files go in the `src/my_project_template` directory. ``` my_project_template |-- __init__.py @@ -72,6 +73,6 @@ How to use the template: `-- my_project_template.py ``` 9. Run all tests with `make test` or different tests with `make behave` or `make pytest`. `make behave` will generate report files and open the browser to the report. -10. Use `python app.py` to run the Flask service app in debug mode. Service will be available at http://localhost:8080/ +10. Use `uv run app.py` to run the Flask service app in debug mode. Service will be available at http://localhost:8080/ 11. Use `make docker-build` to build a docker image using the current `Dockerfile`. 12. `make docker` will build and run the docker image with the service. Service will be available at http://localhost:8080/ diff --git a/pyproject.toml b/pyproject.toml index 8ca4686..ad7543b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,9 @@ +[build-system] +requires = ["uv_build>=0.8.15,<0.9.0"] +build-backend = "uv_build" + [project] -name = "nmdp-python-project-template" +name = "my_project_template" version = "0.0.1" description="Python Project Template. Standardized Python project structure for NMDP projects" requires-python = ">=3.13" diff --git a/tests/unit/test_my_project_template.py b/tests/unit/test_my_project_template.py index 8386e38..6806218 100644 --- a/tests/unit/test_my_project_template.py +++ b/tests/unit/test_my_project_template.py @@ -26,6 +26,9 @@ """Tests for `my_project_template` package.""" import pytest +from my_project_template.algorithm.match import slug_match +from my_project_template.model.slug import SLUG +from my_project_template.model.allele import Allele @pytest.fixture @@ -40,3 +43,25 @@ def supported_genes(): def test_content(supported_genes): """Sample pytest test function with the pytest fixture as an argument.""" assert "HLA-A" in supported_genes + + +def test_slug_match_identical_slugs(): + """Test that identical SLUGs match.""" + allele1 = Allele("HLA-A", "HLA-A*01:01") + allele2 = Allele("HLA-A", "HLA-A*02:01") + slug1 = SLUG(allele1, allele2) + slug2 = SLUG(allele1, allele2) + + assert slug_match(slug1, slug2) is True + + +def test_slug_match_different_slugs(): + """Test that different SLUGs do not match.""" + allele1 = Allele("HLA-A", "HLA-A*01:01") + allele2 = Allele("HLA-A", "HLA-A*02:01") + allele3 = Allele("HLA-A", "HLA-A*03:01") + + slug1 = SLUG(allele1, allele2) + slug2 = SLUG(allele1, allele3) + + assert slug_match(slug1, slug2) is False diff --git a/uv.lock b/uv.lock index 403e2b3..6bb4d88 100644 --- a/uv.lock +++ b/uv.lock @@ -486,9 +486,9 @@ wheels = [ ] [[package]] -name = "nmdp-python-project-template" +name = "my-project-template" version = "0.0.1" -source = { virtual = "." } +source = { editable = "." } [package.dev-dependencies] deploy = [