├── .editorconfig ├── .env.example ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── config.yml ├── dependabot.yml └── workflows │ ├── build.yml │ ├── check-requirements.yml │ ├── check.yml │ ├── coveralls.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .python-version ├── CONTRIBUTORS ├── MANIFEST.in ├── MIT-LICENSE ├── Makefile ├── README.rst ├── TODO ├── djversion ├── __init__.py ├── apps.py ├── conf.py ├── context_processors.py ├── locale │ ├── en │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ └── uk │ │ └── LC_MESSAGES │ │ ├── django.mo │ │ └── django.po ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── print-version.py ├── rest.py ├── templatetags │ ├── __init__.py │ └── djversion_tags.py ├── urls.py └── utils.py ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── management ├── __init__.py └── commands │ ├── __init__.py │ └── test_print-version.py ├── settings.py ├── templatetags ├── __init__.py └── test_djversion_tags.py ├── test_context_processors.py ├── test_rest.py └── test_utils.py /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.py] 11 | indent_style = space 12 | indent_size = 4 13 | 14 | [Makefile] 15 | indent_style = tab 16 | 17 | [*.json] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [*.{yml,yaml}] 22 | indent_style = space 23 | indent_size = 2 24 | 25 | [*.cfg] 26 | indent_style = space 27 | indent_size = 4 28 | 29 | [*.{htm,html}] 30 | indent_style = space 31 | indent_size = 4 32 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NAME=djversion 2 | COVERALLS_REPO_TOKEN= 3 | TWINE_USERNAME=__token__ 4 | TWINE_PASSWORD= 5 | TEST_TWINE_PASSWORD= 6 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | dotenv 2 | layout python 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DCOD-OpenSource/django-project-version/5e5073743935084a20f3a485d489e53a2d029eb9/.gitattributes -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @vint21h @kishinevsky 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Issue Summary 2 | 3 | 4 | 5 | ## Expected Behavior 6 | 7 | 8 | 9 | ## Current Behavior 10 | 11 | 12 | 13 | ## Possible Solution 14 | 15 | 16 | 17 | ## Steps to Reproduce 18 | 19 | 20 | 21 | 22 | ## Context (Environment) 23 | 24 | 25 | 26 | 27 | 28 | 29 | ## Detailed Description 30 | 31 | 32 | 33 | ## Possible Implementation 34 | 35 | 36 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Changes Summary 2 | 3 | 4 | 5 | ## Description 6 | 7 | 8 | 9 | ## Related Issue 10 | 11 | 12 | 13 | 14 | 15 | ## Motivation and Context 16 | 17 | 18 | 19 | 20 | ## How Has This Been Tested? 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | So, because this is not a thing that can produce security problems in the project using it, 6 | security policy is very simple: supported only the last major or minor branch. 7 | 8 | | Version | Supported | 9 | |---------| ------------------ | 10 | | 0.19.x | :white_check_mark: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | If you found something that in your opinion may produce any security problem, please create a [new issue](https://github.com/DCOD-OpenSource/django-project-version/issues/new/). 15 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | allow: 8 | - dependency-name: "all" 9 | dependency-type: "direct" 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "build" 2 | on: 3 | push: 4 | branches: 5 | - "*" 6 | tags: 7 | - "*" 8 | pull_request: 9 | branches: 10 | - "*" 11 | workflow_dispatch: 12 | workflow_call: 13 | env: 14 | NAME: "djversion" 15 | DEFAULT_PYTHON_VERSION: "3.11" 16 | jobs: 17 | check-requirements: 18 | uses: "./.github/workflows/check-requirements.yml" 19 | check: 20 | uses: "./.github/workflows/check.yml" 21 | test: 22 | uses: "./.github/workflows/test.yml" 23 | needs: ["check"] 24 | coveralls: 25 | uses: "./.github/workflows/coveralls.yml" 26 | needs: ["test", "check"] 27 | -------------------------------------------------------------------------------- /.github/workflows/check-requirements.yml: -------------------------------------------------------------------------------- 1 | name: "check-requirements" 2 | on: 3 | workflow_dispatch: 4 | workflow_call: 5 | env: 6 | DEFAULT_PYTHON_VERSION: "3.11" 7 | jobs: 8 | check-requirements: 9 | name: "check-requirements" 10 | runs-on: "ubuntu-latest" 11 | steps: 12 | - name: "Git clone" 13 | id: "git-clone" 14 | uses: "actions/checkout@v3.5.3" 15 | - name: "Set up Python ${{ env.DEFAULT_PYTHON_VERSION }}" 16 | id: "set-up-python" 17 | uses: "actions/setup-python@v4.6.1" 18 | with: 19 | python-version: "${{ env.DEFAULT_PYTHON_VERSION }}" 20 | - name: "Pip cache" 21 | id: "pip-cache" 22 | uses: "actions/cache@v3.3.1" 23 | with: 24 | path: "~/.cache/pip" 25 | key: "${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }}" 26 | restore-keys: | 27 | "${{ runner.os }}-pip-" 28 | - name: "Install requirements" 29 | id: "install-requirements" 30 | run: "make install" 31 | - name: "Check outdated requirements" 32 | id: "check-outdated-requirements" 33 | continue-on-error: true 34 | run: "pip-outdated" 35 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: "check" 2 | on: 3 | workflow_dispatch: 4 | workflow_call: 5 | env: 6 | NAME: "djversion" 7 | DEFAULT_PYTHON_VERSION: "3.11" 8 | jobs: 9 | check: 10 | name: "${{ matrix.toxenv }}" 11 | runs-on: "ubuntu-latest" 12 | strategy: 13 | matrix: 14 | toxenv: ["check", "check-build"] 15 | steps: 16 | - name: "Git clone" 17 | id: "git-clone" 18 | uses: "actions/checkout@v3.5.3" 19 | - name: "Set up Python ${{ env.DEFAULT_PYTHON_VERSION }}" 20 | id: "set-up-python" 21 | uses: "actions/setup-python@v4.6.1" 22 | with: 23 | python-version: "${{ env.DEFAULT_PYTHON_VERSION }}" 24 | - name: "Pip cache" 25 | id: "pip-cache" 26 | uses: "actions/cache@v3.3.1" 27 | with: 28 | path: "~/.cache/pip" 29 | key: "${{ runner.os }}-pip-${{ matrix.toxenv }}-${{ hashFiles('setup.cfg') }}" 30 | restore-keys: | 31 | "${{ runner.os }}-pip-${{ matrix.toxenv }}-" 32 | "${{ runner.os }}-pip-" 33 | - name: "Pre-commit cache" 34 | id: "pre-commit-cache" 35 | uses: "actions/cache@v3.3.1" 36 | with: 37 | path: "~/.cache/pre-commit" 38 | key: "${{ runner.os }}-pre-commit-${{ matrix.toxenv }}-${{ hashFiles('.pre-commit-config.yaml') }}" 39 | restore-keys: | 40 | "${{ runner.os }}-pre-commit-${{ matrix.toxenv }}-" 41 | "${{ runner.os }}-pre-commit-" 42 | - name: "Install requirements" 43 | id: "install-requirements" 44 | run: "make install" 45 | - name: "Run ${{ matrix.toxenv }}" 46 | id: "run" 47 | run: "tox -e ${{ matrix.toxenv }}" 48 | -------------------------------------------------------------------------------- /.github/workflows/coveralls.yml: -------------------------------------------------------------------------------- 1 | name: "coveralls" 2 | on: 3 | workflow_dispatch: 4 | workflow_call: 5 | env: 6 | NAME: "djversion" 7 | DEFAULT_PYTHON_VERSION: "3.11" 8 | jobs: 9 | coveralls: 10 | name: "coveralls" 11 | runs-on: "ubuntu-latest" 12 | steps: 13 | - name: "Git clone" 14 | id: "git-clone" 15 | uses: "actions/checkout@v3.5.3" 16 | - name: "Set up Python ${{ env.DEFAULT_PYTHON_VERSION }}" 17 | id: "set-up-python" 18 | uses: "actions/setup-python@v4.6.1" 19 | with: 20 | python-version: "${{ env.DEFAULT_PYTHON_VERSION }}" 21 | - name: "Pip cache" 22 | id: "pip-cache" 23 | uses: "actions/cache@v3.3.1" 24 | with: 25 | path: "~/.cache/pip" 26 | key: "${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }}" 27 | restore-keys: | 28 | "${{ runner.os }}-pip-" 29 | - name: "Temporarily save coverage statistics" 30 | id: "temporarily-save-coverage-statistics" 31 | uses: "actions/cache@v3.3.1" 32 | with: 33 | path: ".coverage" 34 | key: ".coverage-${{ github.run_id }}-${{ github.run_number }}" 35 | - name: "Install requirements" 36 | id: "install-requirements" 37 | run: "make install" 38 | - name: "Upload coverage report to Coveralls" 39 | id: "upload-coverage-report-to-coveralls" 40 | env: 41 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 42 | run: "coveralls --service=github" 43 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: "test" 2 | on: 3 | workflow_dispatch: 4 | workflow_call: 5 | env: 6 | NAME: "djversion" 7 | jobs: 8 | test: 9 | name: "${{ matrix.python-version }}" 10 | runs-on: "ubuntu-latest" 11 | strategy: 12 | matrix: 13 | python-version: ["3.8", "3.9", "3.10", "3.11"] 14 | steps: 15 | - name: "Git clone" 16 | id: "git-clone" 17 | uses: "actions/checkout@v3.5.3" 18 | - name: "Set up Python ${{ matrix.python-version }}" 19 | id: "set-up-python" 20 | uses: "actions/setup-python@v4.6.1" 21 | with: 22 | python-version: "${{ matrix.python-version }}" 23 | - name: "Pip cache" 24 | id: "pip-cache" 25 | uses: "actions/cache@v3.3.1" 26 | with: 27 | path: "~/.cache/pip" 28 | key: "${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('setup.cfg') }}" 29 | restore-keys: | 30 | "${{ runner.os }}-pip-${{ matrix.python-version }}-" 31 | "${{ runner.os }}-pip-" 32 | - name: "Temporarily save coverage statistics" 33 | id: "temporarily-save-coverage-statistics" 34 | uses: "actions/cache@v3.3.1" 35 | with: 36 | path: ".coverage" 37 | key: ".coverage-${{ github.run_id }}-${{ github.run_number }}" 38 | - name: "Install requirements" 39 | id: "install-requirements" 40 | run: "make install" 41 | - name: "Run tests" 42 | id: "run-tests" 43 | env: 44 | PLATFORM: "${{ matrix.platform }}" 45 | run: "make tox" 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Autogenerated 2 | .*.swp 3 | *.pyc 4 | *.log 5 | *.pot 6 | *.pyo 7 | *.pyd 8 | __pycache__/* 9 | *~ 10 | *.orig 11 | *.bak 12 | .DS_Store 13 | *.save 14 | .mypy_cache/* 15 | .pytest_cache/* 16 | 17 | 18 | # IDE's 19 | .idea/* 20 | *sublime* 21 | *geany* 22 | *komodo* 23 | .vscode/* 24 | .project 25 | .pydevproject 26 | .settings/* 27 | 28 | 29 | # Project 30 | build/* 31 | dist/* 32 | *.egg-info/* 33 | .tox/* 34 | tmp/* 35 | log/* 36 | parts 37 | media/* 38 | *env*/ 39 | static/* 40 | *.pid 41 | .credentials 42 | .env 43 | .coverage 44 | htmlcov 45 | .direnv 46 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: "local" 3 | hooks: 4 | - id: "seed-isort-config" 5 | name: "seed-isort-config" 6 | stages: ["commit"] 7 | language: "system" 8 | pass_filenames: false 9 | entry: "seed-isort-config" 10 | types: ["python"] 11 | - id: "removestar" 12 | name: "removestar" 13 | stages: ["commit"] 14 | language: "system" 15 | entry: "bash -c 'removestar -i \"${NAME}\" tests'" 16 | types: ["python"] 17 | - id: "autoflake" 18 | name: "autoflake" 19 | stages: ["commit"] 20 | language: "system" 21 | entry: "bash -c 'autoflake -r \"${NAME}\" tests'" 22 | types: ["python"] 23 | pass_filenames: false 24 | - id: "isort" 25 | name: "isort" 26 | stages: ["commit"] 27 | language: "system" 28 | entry: "isort" 29 | types: ["python"] 30 | - id: "flynt" 31 | name: "flynt" 32 | stages: ["commit"] 33 | language: "system" 34 | entry: "bash -c 'flynt -ll 88 --no-tf \"${NAME}\" tests'" 35 | types: ["python"] 36 | pass_filenames: false 37 | - id: "black" 38 | name: "black" 39 | stages: ["commit"] 40 | language: "system" 41 | entry: "bash -c 'black \"${NAME}\"'" 42 | types: ["python"] 43 | pass_filenames: false 44 | - id: "yesqa" 45 | name: "yesqa" 46 | stages: ["commit"] 47 | language: "system" 48 | pass_filenames: false 49 | entry: "yesqa" 50 | types: ["python"] 51 | - id: "flake8" 52 | name: "flake8" 53 | stages: ["commit"] 54 | language: "system" 55 | entry: "flake8" 56 | types: ["python"] 57 | - id: "interrogate" 58 | name: "interrogate" 59 | stages: ["commit"] 60 | language: "system" 61 | entry: "bash -c 'interrogate \"${NAME}\" -I -M'" 62 | types: ["python"] 63 | - id: "pylint" 64 | name: "pylint" 65 | stages: ["commit"] 66 | language: "system" 67 | entry: "pylint \"${NAME}\" tests" 68 | types: ["python"] 69 | pass_filenames: false 70 | - id: "bandit" 71 | name: "bandit" 72 | stages: ["commit"] 73 | language: "system" 74 | entry: "bandit -r \"${NAME}\" tests --ini=setup.cfg" 75 | types: ["python"] 76 | pass_filenames: false 77 | - id: "dodgy" 78 | name: "dodgy" 79 | stages: ["commit"] 80 | language: "system" 81 | entry: "dodgy" 82 | types: ["python"] 83 | pass_filenames: false 84 | - id: "darglint" 85 | name: "darglint" 86 | stages: ["commit"] 87 | language: "system" 88 | entry: "darglint" 89 | types: ["python"] 90 | - id: "polint" 91 | name: "polint" 92 | stages: ["commit"] 93 | language: "system" 94 | entry: "polint --ignore=location,unsorted --show-msg" 95 | types: ["pofile"] 96 | pass_filenames: true 97 | - id: "dennis" 98 | name: "dennis" 99 | stages: ["commit"] 100 | language: "system" 101 | entry: "dennis-cmd lint" 102 | types: ["pofile"] 103 | pass_filenames: true 104 | - id: "curlylint" 105 | name: "curlylint" 106 | stages: ["commit"] 107 | language: "system" 108 | entry: "curlylint" 109 | types: ["html", "xml"] 110 | pass_filenames: true 111 | - id: "mypy" 112 | name: "mypy" 113 | stages: ["commit"] 114 | language: "system" 115 | entry: "bash -c 'PYTHONPATH=\"${PYTHONPATH}:${PWD}\" mypy'" 116 | types: ["python"] 117 | pass_filenames: false 118 | - id: "check-manifest" 119 | name: "check-manifest" 120 | stages: ["commit"] 121 | language: "system" 122 | pass_filenames: false 123 | entry: "check-manifest" 124 | - id: "pyroma" 125 | name: "pyroma" 126 | stages: ["commit"] 127 | language: "system" 128 | pass_filenames: false 129 | entry: "pyroma -d ." 130 | types: ["python"] 131 | - id: "check-wheel-contents" 132 | name: "check-wheel-contents" 133 | stages: ["commit"] 134 | language: "system" 135 | pass_filenames: false 136 | entry: "bash -c 'make build -B && check-wheel-contents dist'" 137 | types: ["python"] 138 | - id: "dotenv-linter" 139 | name: "dotenv-linter" 140 | entry: "dotenv-linter" 141 | language: "system" 142 | stages: ["commit"] 143 | types: ["text"] 144 | files: '\.env*' 145 | exclude: ".envrc" 146 | - id: "rstcheck" 147 | name: "rstcheck" 148 | entry: "rstcheck" 149 | language: "system" 150 | stages: ["commit"] 151 | types: ["rst"] 152 | - id: "markdown-linter" 153 | name: "markdown-linter" 154 | entry: "pymarkdown -d md013 scan" 155 | language: "system" 156 | stages: ["commit"] 157 | types: ["markdown"] 158 | - repo: "https://github.com/pre-commit/pre-commit-hooks" 159 | rev: "v4.5.0" 160 | hooks: 161 | - id: "check-added-large-files" 162 | - id: "check-ast" 163 | - id: "check-case-conflict" 164 | - id: "check-docstring-first" 165 | - id: "check-executables-have-shebangs" 166 | - id: "check-merge-conflict" 167 | - id: "check-symlinks" 168 | - id: "check-yaml" 169 | - id: "debug-statements" 170 | - id: "detect-private-key" 171 | - id: "end-of-file-fixer" 172 | - id: "forbid-new-submodules" 173 | - id: "trailing-whitespace" 174 | - repo: "https://github.com/Anadea/pre-commit-config-shellcheck" 175 | rev: "0.3.4" 176 | hooks: 177 | - id: "pre-commit-config-shellcheck" 178 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.11.6 2 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Contributors ordered by first contribution. 2 | 3 | 4 | Oleksii Andrushevych 5 | Marco A Rojas 6 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | prune tests* 2 | recursive-include djversion *.po 3 | recursive-include djversion *.mo 4 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024, DCOD 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .ONESHELL: 2 | default: help 3 | PHONY: install tox test makemessages compilemessages bumpversion build sign check check-build check-upload upload clean coveralls release help 4 | TEST_PYPI_URL ?= https://test.pypi.org/legacy/ 5 | NAME ?= djversion 6 | EXTENSIONS ?= py,html,txt,xml 7 | TRASH_DIRS ?= build dist *.egg-info .tox .mypy_cache .pytest_cache __pycache__ htmlcov 8 | TRASH_FILES ?= .coverage 9 | BUILD_TYPES ?= bdist_wheel sdist 10 | VERSION ?= `python -c "import configparser; config = configparser.ConfigParser(); config.read('setup.cfg'); print(config['metadata']['version']);"` 11 | 12 | 13 | install: 14 | pip install .[test,rest,git];\ 15 | 16 | tox: 17 | tox;\ 18 | 19 | test: 20 | bash -c 'PYTHONPATH="$${PYTHONPATH}:$${PWD}" py.test --cov=$(NAME) --modules-durations=0 --functions-durations=0 --instafail $(TESTS)';\ 21 | 22 | makemessages: 23 | for locale in `ls $(NAME)/locale`; do\ 24 | django-admin makemessages --locale=$${locale} --extension=$(EXTENSIONS);\ 25 | done;\ 26 | 27 | compilemessages: 28 | django-admin compilemessages;\ 29 | 30 | bumpversion: 31 | git tag -a $(VERSION) -m "v$(VERSION)";\ 32 | 33 | build: 34 | python setup.py $(BUILD_TYPES);\ 35 | 36 | sign: 37 | for package in `ls dist`; do\ 38 | gpg -a --detach-sign dist/$${package};\ 39 | done;\ 40 | 41 | check: 42 | bash -c 'NAME="$(NAME)" pre-commit run --all-files';\ 43 | 44 | check-build: 45 | twine check dist/*;\ 46 | 47 | check-upload: 48 | twine upload --skip-existing -s --repository-url $(TEST_PYPI_URL) -u __token__ -p $${TEST_TWINE_PASSWORD} dist/*;\ 49 | 50 | upload: 51 | twine upload --skip-existing -s dist/*;\ 52 | 53 | clean: 54 | for file in $(TRASH_FILES); do\ 55 | find -iname $${file} -print0 | xargs -0 rm -rf;\ 56 | done;\ 57 | for dir in $(TRASH_DIRS); do\ 58 | find -type d -name $${dir} ! -path "*/.direnv/*" -print0 | xargs -0 rm -rf;\ 59 | done;\ 60 | 61 | coveralls: 62 | coveralls;\ 63 | 64 | release: 65 | make clean && \ 66 | make bumpversion && \ 67 | git co master && \ 68 | git merge dev && \ 69 | git co dev && \ 70 | git push --all && \ 71 | git push --tags && \ 72 | make build && \ 73 | make sign && \ 74 | make check-build && \ 75 | make check-upload && \ 76 | make upload && \ 77 | make clean;\ 78 | 79 | help: 80 | @echo " help:" 81 | @echo " Show this help." 82 | @echo " install:" 83 | @echo " Install requirements." 84 | @echo " tox:" 85 | @echo " Run tox." 86 | @echo " test:" 87 | @echo " Run tests, can specify tests with 'TESTS' variable." 88 | @echo " makemessages:" 89 | @echo " Harvest translations." 90 | @echo " compilemessages:" 91 | @echo " Compile translations." 92 | @echo " bumpversion:" 93 | @echo " Tag current code revision with version." 94 | @echo " build:" 95 | @echo " Build python packages, can specify packages types with 'BUILD_TYPES' variable." 96 | @echo " sign:" 97 | @echo " Sign python packages." 98 | @echo " check:" 99 | @echo " Perform some code checks." 100 | @echo " check-build:" 101 | @echo " Run twine checks." 102 | @echo " check-upload:" 103 | @echo " Upload package to test PyPi using twine." 104 | @echo " upload:" 105 | @echo " Upload package to PyPi using twine." 106 | @echo " clean:" 107 | @echo " Recursively delete useless autogenerated files and directories, directories and files lists can be overriden through 'TRASH_DIRS' and 'TRASH_FILES' variables." 108 | @echo " coveralls:" 109 | @echo " Upload coverage report to Coveralls." 110 | @echo " release:" 111 | @echo " Release code." 112 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | A django-project-version documentation 2 | ====================================== 3 | 4 | |GitHub|_ |Coveralls|_ |pypi-license|_ |pypi-version|_ |pypi-python-version|_ |pypi-django-version|_ |pypi-format|_ |pypi-wheel|_ |pypi-status|_ 5 | 6 | *django-project-version is a Django reusable app to show your project version* 7 | 8 | .. contents:: 9 | 10 | Installation 11 | ------------ 12 | * Obtain your copy of source code from the git repository: ``$ git clone https://github.com/DCOD-OpenSource/django-project-version.git``. Or download the latest release from https://github.com/DCOD-OpenSource/django-project-version/tags/. 13 | * Run ``$ python ./setup.py install`` from the repository source tree or unpacked archive. Or use pip: ``$ pip install django-project-version``. 14 | 15 | Configuration 16 | ------------- 17 | * Add ``"djversion"`` to ``settings.INSTALLED_APPS``. 18 | 19 | .. code-block:: python 20 | 21 | # settings.py 22 | 23 | INSTALLED_APPS += [ 24 | "djversion", 25 | ] 26 | 27 | Settings 28 | -------- 29 | ``DJVERSION_VERSION`` 30 | Contains project version. Defaults to ``None``. 31 | 32 | ``DJVERSION_UPDATED`` 33 | Contains project update date or datetime. Defaults to ``None``. 34 | 35 | ``DJVERSION_FORMAT_STRING`` 36 | Contains version and updated format string. Defaults to ``"{version} ({updated})"``. 37 | 38 | ``DJVERSION_GIT_REPO_PATH`` 39 | Contains path to git repository from where version info can get. Defaults to ``None``. 40 | 41 | ``DJVERSION_GIT_USE_TAG`` 42 | Indicate usage of git repository current tag as project version. Defaults to ``False``. 43 | 44 | ``DJVERSION_GIT_USE_COMMIT`` 45 | Indicate usage of git repository last commit hash as project version. Defaults to ``False``. 46 | 47 | Usage 48 | ----- 49 | If you want always have ``"VERSION"`` variable in templates context, just add ``"djversion.context_processors.version"`` to ``settings.TEMPLATE_CONTEXT_PROCESSORS`` 50 | 51 | .. code-block:: python 52 | 53 | # settings.py 54 | 55 | TEMPLATE_CONTEXT_PROCESSORS += [ 56 | "djversion.context_processors.version", 57 | ] 58 | 59 | 60 | Or you can use ``project_version`` templatetag which can be loaded from ``djversion_tags``. 61 | 62 | .. code-block:: django 63 | 64 | {# footer.html #} 65 | 66 | {% load djversion_tags %} 67 | 68 | {% project_version as VERSION %} 69 | {{ VERSION }} 70 | 71 | Also simple management command ``print-version`` which prints project version to stdout is available. Just run: 72 | 73 | .. code-block:: bash 74 | 75 | django-admin print-version 76 | 77 | or 78 | 79 | .. code-block:: bash 80 | 81 | ./manage.py print-version 82 | 83 | 84 | Advanced features 85 | ----------------- 86 | If you want to have REST-style view with your project version: 87 | 88 | * Install ``django-project-version`` with additional dependencies: ``$ pip install django-project-version[rest]``. 89 | * Extend you ``settings.INSTALLED_APPS`` by adding ``"rest_framework"``. 90 | 91 | .. code-block:: python 92 | 93 | # settings.py 94 | 95 | INSTALLED_APPS += [ 96 | "rest_framework", 97 | ] 98 | 99 | * Add ``"djversion"`` to your URLs definitions: 100 | 101 | .. code-block:: python 102 | 103 | # urls.py 104 | 105 | from django.urls import re_path, include 106 | 107 | 108 | urlpatterns += [ 109 | re_path(r"^version/", include("djversion.urls")), 110 | ] 111 | 112 | Or to use information from the project git repository as project version: 113 | 114 | * Install ``django-project-version`` with additional dependencies: ``$ pip install django-project-version[git]``. 115 | * Configure git related settings. 116 | 117 | Contributing 118 | ------------ 119 | - `Fork it `_ 120 | - Install `GNU Make `_ 121 | - Install and configure `pyenv `_ and `pyenv-virtualenv plugin `_ 122 | - Install and configure `direnv `_ 123 | - Create environment config from example 124 | 125 | .. code-block:: bash 126 | 127 | cp .env.example .env 128 | 129 | - Install development dependencies: 130 | 131 | .. code-block:: bash 132 | 133 | make install 134 | 135 | - Create your fix/feature branch: 136 | 137 | .. code-block:: bash 138 | 139 | git checkout -b my-new-fix-or-feature 140 | 141 | - Check code style and moreover: 142 | 143 | .. code-block:: bash 144 | 145 | make check 146 | 147 | - Run tests: 148 | 149 | .. code-block:: bash 150 | 151 | make test 152 | 153 | - Push to the branch: 154 | 155 | .. code-block:: bash 156 | 157 | git push origin my-new-fix-or-feature 158 | 159 | - `Create a new Pull Request `_ 160 | 161 | Licensing 162 | --------- 163 | django-project-version uses the MIT license. Please check the MIT-LICENSE file for more details. 164 | 165 | Contacts 166 | -------- 167 | **Project Website**: https://github.com/DCOD-OpenSource/django-project-version/ 168 | 169 | **Author**: DCOD 170 | 171 | For contributors list see CONTRIBUTORS file. 172 | 173 | 174 | .. |GitHub| image:: https://github.com/DCOD-OpenSource/django-project-version/workflows/build/badge.svg 175 | :alt: GitHub 176 | .. |Coveralls| image:: https://coveralls.io/repos/github/DCOD-OpenSource/django-project-version/badge.svg?branch=master 177 | :alt: Coveralls 178 | .. |pypi-license| image:: https://img.shields.io/pypi/l/django-project-version 179 | :alt: License 180 | .. |pypi-version| image:: https://img.shields.io/pypi/v/django-project-version 181 | :alt: Version 182 | .. |pypi-django-version| image:: https://img.shields.io/pypi/djversions/django-project-version 183 | :alt: Supported Django version 184 | .. |pypi-python-version| image:: https://img.shields.io/pypi/pyversions/django-project-version 185 | :alt: Supported Python version 186 | .. |pypi-format| image:: https://img.shields.io/pypi/format/django-project-version 187 | :alt: Package format 188 | .. |pypi-wheel| image:: https://img.shields.io/pypi/wheel/django-project-version 189 | :alt: Python wheel support 190 | .. |pypi-status| image:: https://img.shields.io/pypi/status/django-project-version 191 | :alt: Package status 192 | .. _GitHub: https://github.com/DCOD-OpenSource/django-project-version/actions/ 193 | .. _Coveralls: https://coveralls.io/github/DCOD-OpenSource/django-project-version?branch=master 194 | .. _pypi-license: https://pypi.org/project/django-project-version/ 195 | .. _pypi-version: https://pypi.org/project/django-project-version/ 196 | .. _pypi-django-version: https://pypi.org/project/django-project-version/ 197 | .. _pypi-python-version: https://pypi.org/project/django-project-version/ 198 | .. _pypi-format: https://pypi.org/project/django-project-version/ 199 | .. _pypi-wheel: https://pypi.org/project/django-project-version/ 200 | .. _pypi-status: https://pypi.org/project/django-project-version/ 201 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DCOD-OpenSource/django-project-version/5e5073743935084a20f3a485d489e53a2d029eb9/TODO -------------------------------------------------------------------------------- /djversion/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = ["default_app_config"] 5 | 6 | 7 | default_app_config: str = "djversion.apps.DjangoDjversionConfig" 8 | -------------------------------------------------------------------------------- /djversion/apps.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from django.apps import AppConfig 4 | from django.utils.translation import gettext_lazy as _ 5 | 6 | 7 | __all__: List[str] = ["DjangoDjversionConfig"] 8 | 9 | 10 | class DjangoDjversionConfig(AppConfig): 11 | """Application config.""" 12 | 13 | name: str = "djversion" 14 | verbose_name: str = _("Django project version") # type: ignore 15 | -------------------------------------------------------------------------------- /djversion/conf.py: -------------------------------------------------------------------------------- 1 | from datetime import date, datetime 2 | from typing import List, Union, Optional 3 | 4 | from appconf import AppConf 5 | from django.conf import settings 6 | 7 | 8 | __all__: List[str] = ["settings"] 9 | 10 | 11 | class DjangoDjversionAppConf(AppConf): 12 | """Django djversion settings.""" 13 | 14 | VERSION: Optional[str] = getattr(settings, "DJVERSION_VERSION", None) 15 | UPDATED: Optional[Union[datetime, date]] = getattr( 16 | settings, "DJVERSION_UPDATED", None 17 | ) 18 | FORMAT_STRING: str = getattr( 19 | settings, "DJVERSION_FORMAT_STRING", "{version} ({updated})" # noqa: FS003 20 | ) 21 | GIT_REPO_PATH: Optional[str] = getattr(settings, "DJVERSION_GIT_REPO_PATH", None) 22 | GIT_USE_TAG: bool = getattr(settings, "DJVERSION_GIT_USE_TAG", False) 23 | GIT_USE_COMMIT: bool = getattr(settings, "DJVERSION_GIT_USE_COMMIT", False) 24 | 25 | class Meta: 26 | """Config settings.""" 27 | 28 | prefix: str = "djversion" 29 | -------------------------------------------------------------------------------- /djversion/context_processors.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List 2 | 3 | from django.http import HttpRequest 4 | 5 | from djversion.utils import get_version 6 | 7 | 8 | __all__: List[str] = ["version"] 9 | 10 | 11 | def version(request: HttpRequest) -> Dict[str, str]: 12 | """ 13 | Return formatted version string named as "VERSION" to context. 14 | 15 | :param request: django HTTP request object 16 | :type request: HttpRequest 17 | :return: formatted version string named as "VERSION" 18 | :rtype: Dict[str, str] 19 | """ 20 | return {"VERSION": get_version()} 21 | -------------------------------------------------------------------------------- /djversion/locale/en/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DCOD-OpenSource/django-project-version/5e5073743935084a20f3a485d489e53a2d029eb9/djversion/locale/en/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /djversion/locale/en/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | #, fuzzy 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: django-project-version 0.19.0\n" 5 | "Report-Msgid-Bugs-To: \n" 6 | "POT-Creation-Date: 2024-01-08 18:40+0200\n" 7 | "PO-Revision-Date: 2019-09-11 04:53+0300\n" 8 | "Last-Translator: Oleksii Andrushevych \n" 9 | "Language-Team: Oleksii Andrushevych \n" 10 | "Language: en\n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: 8bit\n" 14 | 15 | #: djversion/apps.py:14 16 | msgid "Django project version" 17 | msgstr "Django project version" 18 | 19 | #: djversion/management/commands/print-version.py:15 20 | msgid "Print project version" 21 | msgstr "Print project version" 22 | 23 | #: djversion/rest.py:19 24 | msgid "version" 25 | msgstr "version" 26 | 27 | #: djversion/rest.py:19 28 | msgid "project version" 29 | msgstr "project version" 30 | -------------------------------------------------------------------------------- /djversion/locale/uk/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DCOD-OpenSource/django-project-version/5e5073743935084a20f3a485d489e53a2d029eb9/djversion/locale/uk/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /djversion/locale/uk/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | #, fuzzy 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: django-project-version 0.19.0\n" 5 | "Report-Msgid-Bugs-To: \n" 6 | "POT-Creation-Date: 2024-01-08 18:40+0200\n" 7 | "PO-Revision-Date: 2019-09-11 04:53+0300\n" 8 | "Last-Translator: Oleksii Andrushevych \n" 9 | "Language-Team: Oleksii Andrushevych \n" 10 | "Language: uk\n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: 8bit\n" 14 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 15 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 16 | 17 | #: djversion/apps.py:14 18 | msgid "Django project version" 19 | msgstr "Django project version" 20 | 21 | #: djversion/management/commands/print-version.py:15 22 | msgid "Print project version" 23 | msgstr "Надрукувати версію проекту" 24 | 25 | #: djversion/rest.py:19 26 | msgid "version" 27 | msgstr "версія" 28 | 29 | #: djversion/rest.py:19 30 | msgid "project version" 31 | msgstr "версія проекту" 32 | -------------------------------------------------------------------------------- /djversion/management/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /djversion/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /djversion/management/commands/print-version.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, List 2 | 3 | from django.core.management.base import BaseCommand 4 | from django.utils.translation import gettext_lazy as _ 5 | 6 | from djversion.utils import get_version 7 | 8 | 9 | __all__: List[str] = ["Command"] 10 | 11 | 12 | class Command(BaseCommand): 13 | """Version management command.""" 14 | 15 | help: str = str(_("Print project version")) # noqa: A003 16 | 17 | def handle(self, *args: List[Any], **kwargs: Dict[str, Any]) -> None: 18 | """ 19 | Perform command. 20 | 21 | :param args: additional args 22 | :type args: List[Any] 23 | :param kwargs: additional args 24 | :type kwargs: Dict[str, Any] 25 | """ 26 | self.stdout.write(get_version()) 27 | -------------------------------------------------------------------------------- /djversion/rest.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, List, Type 2 | 3 | from rest_framework.response import Response 4 | from rest_framework.generics import GenericAPIView 5 | from django.utils.translation import gettext_lazy as _ 6 | from rest_framework.serializers import CharField, Serializer 7 | from rest_framework.permissions import AllowAny, BasePermission 8 | 9 | from djversion.utils import get_version 10 | 11 | 12 | __all__: List[str] = ["VersionSerializer", "VersionView"] 13 | 14 | 15 | class VersionSerializer(Serializer): # type: ignore 16 | """Version serializer.""" 17 | 18 | version = CharField( 19 | label=_("version"), help_text=_("project version"), read_only=True 20 | ) 21 | 22 | 23 | class VersionView(GenericAPIView): # type: ignore 24 | """Version view.""" 25 | 26 | permission_classes: List[Type[BasePermission]] = [AllowAny] 27 | serializer_class: Type[VersionSerializer] = VersionSerializer 28 | pagination_class = None 29 | filter_backends = None # type: ignore 30 | 31 | def get(self, request, **kwargs: Dict[str, Any]) -> Response: 32 | """ 33 | Handle GET http request. 34 | 35 | :param request: django request instance 36 | :type request: HttpRequest 37 | :param kwargs: additional args 38 | :type kwargs: Dict[str, Any] 39 | :return: serialized custom queryset response 40 | :rtype: Response 41 | """ 42 | data: Dict[str, str] = {"version": get_version()} 43 | serializer = self.get_serializer(instance=data) 44 | 45 | return Response(serializer.data) 46 | -------------------------------------------------------------------------------- /djversion/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /djversion/templatetags/djversion_tags.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from django import template 4 | 5 | from djversion.utils import get_version 6 | 7 | 8 | __all__: List[str] = ["project_version"] 9 | 10 | 11 | register = template.Library() 12 | 13 | 14 | @register.simple_tag() 15 | def project_version() -> str: 16 | """ 17 | Formatted version string templatetag. 18 | 19 | :return: formatted project version 20 | :rtype: str 21 | """ 22 | return get_version() 23 | -------------------------------------------------------------------------------- /djversion/urls.py: -------------------------------------------------------------------------------- 1 | from typing import List, Union 2 | 3 | from django.urls import re_path 4 | from django.urls.resolvers import URLPattern, URLResolver 5 | 6 | from djversion.rest import VersionView 7 | 8 | 9 | __all__: List[str] = ["urlpatterns"] 10 | 11 | 12 | urlpatterns: List[Union[URLPattern, URLResolver]] = [ 13 | re_path(r"^$", VersionView.as_view(), name="version-view") 14 | ] 15 | -------------------------------------------------------------------------------- /djversion/utils.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from datetime import date, datetime 3 | 4 | from django.templatetags.l10n import localize 5 | 6 | from djversion.conf import settings 7 | 8 | 9 | # trying to import git lib in case of this functionality is unnecessary 10 | try: 11 | from git import Repo 12 | except ImportError: 13 | Repo = None # type: ignore 14 | 15 | 16 | __all__: List[str] = ["get_version"] 17 | 18 | 19 | def get_version() -> str: # noqa: CCR001 20 | """ 21 | Format version string. 22 | 23 | :return: formatted version string 24 | :rtype: str 25 | """ 26 | version = "" 27 | if all( 28 | [ 29 | settings.DJVERSION_VERSION, 30 | settings.DJVERSION_UPDATED, 31 | any( 32 | [ 33 | isinstance(settings.DJVERSION_UPDATED, date), 34 | isinstance(settings.DJVERSION_UPDATED, datetime), 35 | ] 36 | ), 37 | settings.DJVERSION_FORMAT_STRING, 38 | ] 39 | ): 40 | version = settings.DJVERSION_FORMAT_STRING.format( 41 | version=settings.DJVERSION_VERSION, 42 | updated=localize(settings.DJVERSION_UPDATED), 43 | ) 44 | elif settings.DJVERSION_VERSION: 45 | version = settings.DJVERSION_VERSION 46 | elif settings.DJVERSION_UPDATED: 47 | version = ( 48 | localize(settings.DJVERSION_UPDATED) 49 | if any( 50 | [ 51 | isinstance(settings.DJVERSION_UPDATED, date), 52 | isinstance(settings.DJVERSION_UPDATED, datetime), 53 | ] 54 | ) 55 | else "" 56 | ) 57 | elif all([Repo, settings.DJVERSION_GIT_REPO_PATH]): # type: ignore 58 | try: 59 | repo = Repo(settings.DJVERSION_GIT_REPO_PATH) # type: ignore 60 | if settings.DJVERSION_GIT_USE_TAG: # type: ignore 61 | tag = next( 62 | (tag for tag in repo.tags if tag.commit == repo.head.commit), None 63 | ) 64 | version = tag.name if tag else "" 65 | elif settings.DJVERSION_GIT_USE_COMMIT: # type: ignore 66 | version = repo.head.commit.hexsha if repo.head.commit else "" 67 | else: 68 | version = "" 69 | except Exception: # noqa: PIE786 70 | version = "" 71 | else: 72 | version = "" 73 | 74 | return version # noqa: R504 75 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = django-project-version 3 | version = 0.19.0 4 | description = Django reusable app to show your project version 5 | python_requires = >=3.8 6 | license_files = 7 | MIT-LICENSE 8 | author = DCOD 9 | author_email = contact@d-cod.com 10 | url = https://github.com/DCOD-OpenSource/django-project-version/ 11 | classifiers = 12 | Development Status :: 5 - Production/Stable 13 | Environment :: Plugins 14 | Framework :: Django :: 3.2 15 | Framework :: Django :: 4.0 16 | Framework :: Django :: 4.1 17 | Framework :: Django :: 4.2 18 | Framework :: Django :: 5.0 19 | License :: OSI Approved :: MIT License 20 | Operating System :: Unix 21 | Programming Language :: Python :: 3.8 22 | Programming Language :: Python :: 3.9 23 | Programming Language :: Python :: 3.10 24 | Programming Language :: Python :: 3.11 25 | Topic :: Utilities 26 | license = MIT 27 | long_description = file:README.rst 28 | long_description_content_type = text/x-rst 29 | keywords = django,version,project,django-project-version 30 | 31 | [options] 32 | packages = find: 33 | zip_safe = False 34 | include_package_data = True 35 | test_suite = tests 36 | install_requires = 37 | django>=3.2,<5.1 38 | django-appconf>=1.0.3 39 | 40 | [options.extras_require] 41 | test = 42 | attrs==23.2.0 43 | autoflake==2.2.1 44 | bandit==1.7.6 45 | black==23.12.1 46 | check-manifest==0.49 47 | check-wheel-contents==0.6.0 48 | coverage==6.5.0 # do not update before coveralls start 7.x support 49 | coveralls==3.3.1 50 | curlylint==0.13.1 51 | darglint==1.8.1 52 | dennis==1.1.0 53 | django-stubs==4.2.7 54 | djangorestframework-stubs==3.14.5 55 | dlint==0.14.1 56 | dodgy==0.2.1 57 | dotenv-linter==0.4.0 58 | flake8-annotations-complexity==0.0.8 59 | flake8-annotations-coverage==0.0.6 60 | flake8-blind-except==0.2.1 61 | flake8-boolean-trap==1.0.1 62 | flake8-broken-line==1.0.0 63 | flake8-bugbear==23.12.2 64 | flake8-builtins==2.2.0 65 | flake8-coding==1.3.2 66 | flake8-cognitive-complexity==0.1.0 67 | flake8-comprehensions==3.14.0 68 | flake8-datetimez==20.10.0 69 | flake8-debugger==4.1.2 70 | flake8-django==1.4 71 | flake8-docstrings==1.7.0 72 | flake8-eradicate==1.5.0 73 | flake8-executable==2.1.3 74 | flake8-expression-complexity==0.0.11 75 | flake8-fixme==1.1.1 76 | flake8-functions==0.0.8 77 | flake8-gettext==0.0.0.1 78 | flake8-logging-format==0.9.0 79 | flake8-mutable==1.2.0 80 | flake8-no-implicit-concat==0.3.5 81 | flake8-no-pep420==2.7.0 82 | flake8-pie==0.16.0 83 | flake8-print==5.0.0 84 | flake8-raise==0.0.5 85 | flake8-return==1.2.0 86 | flake8-self==0.2.2 87 | flake8-simplify==0.21.0 88 | flake8-spellcheck==0.28.0 89 | flake8-super==0.1.3 90 | flake8-tidy-imports==4.10.0 91 | flake8-todos==0.3.0 92 | flake8-typing-imports==1.15.0 93 | flake8-use-fstring==1.4 94 | flake8-use-pathlib==0.3.0 95 | flake8-variables-names==0.0.6 96 | flake8==6.0.0 97 | flynt==1.0.1 98 | importlib-metadata==7.0.1 99 | interrogate==1.5.0 100 | isort==5.13.2 101 | mypy==1.8.0 102 | pep8-naming==0.13.3 103 | perflint==0.7.3 104 | pip-outdated==0.6.0 105 | polint==0.4 106 | pre-commit-hooks==4.5.0 107 | pre-commit==3.5.0 108 | pygments==2.17.2 109 | pylint-django==2.5.5 110 | pylint==2.17.4 111 | pyroma==4.2 112 | pytest-cov==4.1.0 113 | pytest-django==4.7.0 114 | pytest-extra-durations==0.1.3 115 | pytest-instafail==0.5.0 116 | pytest-sugar==0.9.7 117 | pytest-timer[termcolor]==1.00 118 | pytest==7.4.4 119 | pymarkdownlnt==0.9.15 120 | readme_renderer==42.0 121 | removestar==1.5 122 | rstcheck==6.2.0 123 | seed-isort-config==2.2.0 124 | tabulate==0.9.0 125 | tox-gh-actions==3.2.0 126 | tox==4.11.4 127 | twine==4.0.2 128 | tryceratops==2.3.2 129 | wheel==0.42.0 130 | yesqa==1.5.0 131 | rest = 132 | djangorestframework>=3.10.3 133 | git = 134 | gitpython>=3.0.2 135 | 136 | [options.packages.find] 137 | exclude = 138 | tests.* 139 | tests 140 | 141 | [bdist_wheel] 142 | universal = False 143 | 144 | [sdist] 145 | formats = zip 146 | 147 | 148 | [mypy] 149 | files = djversion,tests 150 | check_untyped_defs = True 151 | disallow_any_generics = True 152 | disallow_untyped_calls = True 153 | ignore_errors = False 154 | ignore_missing_imports = True 155 | implicit_reexport = True 156 | strict_optional = True 157 | strict_equality = True 158 | no_implicit_optional = True 159 | warn_unused_ignores = True 160 | warn_redundant_casts = True 161 | warn_unused_configs = True 162 | warn_unreachable = True 163 | warn_no_return = True 164 | plugins = mypy_django_plugin.main,mypy_drf_plugin.main 165 | 166 | [mypy.plugins.django-stubs] 167 | django_settings_module = tests.settings 168 | 169 | 170 | [flake8] 171 | max-line-length = 88 172 | select = B,C,D,E,F,W,T4,C4,TAE,T,M511,T100,TYP,A,EXE,CFQ,SIM,DUO,N,DJ,ECE,FS,R,CCR,NIC,PL,I25,R1,SLF001,DTZ,GT,G,INP,PIE,B901,FBT,TRY 173 | doctests = True 174 | ignore = C101,D100,D104,D401,FBT003 175 | max-annotations-complexity = 5 176 | max-expression-complexity = 5 177 | max-cognitive-complexity = 5 178 | min-python-version = 3.7 179 | exclude = setup.py 180 | dictionaries = en_US,python,technical,django 181 | spellcheck-targets = comments,names 182 | eradicate-whitelist = mypy 183 | 184 | 185 | [check-manifest] 186 | ignore = 187 | .editorconfig 188 | .env 189 | .env.example 190 | .envrc 191 | .gitattributes 192 | .github 193 | .gitignore 194 | .pre-commit-config.yaml 195 | .python-version 196 | CONTRIBUTORS 197 | COPYING 198 | Makefile 199 | MIT-LICENSE 200 | tests 201 | tests.* 202 | TODO 203 | ignore-bad-ideas = 204 | *.mo 205 | 206 | 207 | [coverage:run] 208 | branch = True 209 | source = djversion 210 | omit = 211 | */__init__.py 212 | djversion/apps.py 213 | 214 | [coverage:report] 215 | omit = 216 | */__init__.py 217 | djversion/apps.py 218 | exclude_lines = 219 | pragma: no cover 220 | 221 | 222 | [isort] 223 | balanced_wrapping = True 224 | combine_as_imports = True 225 | default_section = FIRSTPARTY 226 | force_grid_wrap = 0 227 | force_sort_within_sections = True 228 | force_to_top = True 229 | include_trailing_comma = True 230 | known_first_party = djversion 231 | line_length = 88 232 | lines_after_imports = 2 233 | length_sort = True 234 | multi_line_output = 3 235 | use_parentheses = True 236 | virtual_env = $VIRTUAL_ENV 237 | known_third_party = appconf,django,git,rest_framework,setuptools 238 | 239 | 240 | [darglint] 241 | docstring_style = sphinx 242 | 243 | 244 | [bandit] 245 | skips = B507 246 | tests = B101,B102,B103,B104,B105,B106,B107,B108,B110,B112,B201,B301,B302,B303,B304,B305,B306,B307,B308,B310,B311,B312,B313,B314,B315,B316,B317,B318,B319,B320,B321,B323,B324,B401,B402,B403,B404,B405,B406,B407,B408,B409,B410,B411,B412,B413,B501,B502,B503,B504,B505,B506,B601,B602,B603,B604,B605,B606,B607,B608,B609,B610,B611,B701,B702,B703 247 | 248 | 249 | [tool:check-wheel-contents] 250 | ignore = W004,W002 251 | 252 | 253 | [tox:tox] 254 | skip_missing_interpreters = True 255 | skipsdist = False 256 | envlist = 257 | {py38,py39,py310,py311}-3.2.x 258 | {py38,py39,py310,py311}-4.0.x 259 | {py38,py39,py310,py311}-4.1.x 260 | {py38,py39,py310,py311}-4.2.x 261 | {py310,py311}-5.0.x 262 | check 263 | check-build 264 | 265 | [testenv] 266 | usedevelop = True 267 | setenv = 268 | PYTHONDONTWRITEBYTECODE=1 269 | deps = 270 | 3.2.x: Django>=3.2,<4.0 271 | 4.0.x: Django>=4.0,<4.1 272 | 4.1.x: Django>=4.1,<4.2 273 | 4.2.x: Django>=4.2,<5.0 274 | 5.0.x: Django>=5.0,<5.1 275 | commands= 276 | make install 277 | make test 278 | allowlist_externals = 279 | make 280 | 281 | [testenv:check] 282 | skip_install = True 283 | commands = 284 | make check 285 | allowlist_externals = 286 | make 287 | 288 | [testenv:check-build] 289 | skip_install = True 290 | commands = 291 | make build -B 292 | make check-build -B 293 | allowlist_externals = 294 | make 295 | 296 | 297 | [gh-actions] 298 | python = 299 | 3.8: py38 300 | 3.9: py39 301 | 3.10: py310 302 | 3.11: py311 303 | 304 | 305 | [pylint.MASTER] 306 | ignore = CVS 307 | ignore-patterns = 308 | persistent = yes 309 | load-plugins = pylint_django, 310 | perflint, 311 | pylint.extensions.bad_builtin, 312 | pylint.extensions.code_style, 313 | pylint.extensions.comparison_placement, 314 | pylint.extensions.consider_refactoring_into_while_condition, 315 | pylint.extensions.docparams, 316 | pylint.extensions.dunder, 317 | pylint.extensions.eq_without_hash, 318 | pylint.extensions.for_any_all, 319 | pylint.extensions.magic_value, 320 | pylint.extensions.mccabe, 321 | pylint.extensions.no_self_use, 322 | pylint.extensions.overlapping_exceptions, 323 | pylint.extensions.private_import, 324 | pylint.extensions.redefined_loop_name, 325 | pylint.extensions.redefined_variable_type, 326 | pylint.extensions.set_membership, 327 | pylint.extensions.typing, 328 | pylint.extensions.while_used 329 | jobs = 1 330 | unsafe-load-any-extension = no 331 | extension-pkg-whitelist = 332 | optimize-ast = no 333 | 334 | [pylint.'MESSAGES CONTROL'] 335 | confidence = 336 | disable = all 337 | enable = E0001,E0100,E0101,E0102,E0103,E0104,E0105,E0106,E0107,E0110, 338 | E0113,E0114,E0115,E0116,E0117,E0108,E0202,E0203,E0211,E0236, 339 | E0238,E0239,E0240,E0241,E0301,E0302,E0601,E0603,E0604,E0701, 340 | E0702,E0703,E0704,E0710,E0711,E0712,E1003,E1102,E1111,E0112, 341 | E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1132,E1200,E1201, 342 | E1205,E1206,E1300,E1301,E1302,E1303,E1304,E1305,E1306, 343 | C0123,C0200,C0303,C1001, 344 | W0101,W0102,W0104,W0105,W0106,W0107,W0108,W0109,W0110,W0120, 345 | W0122,W0124,W0150,W0199,W0221,W0222,W0233,W0404,W0410,W0601, 346 | W0602,W0604,W0611,W0612,W0622,W0623,W0702,W0705,W0711,W1300, 347 | W1301,W1302,W1303,,W1305,W1306,W1307 348 | R0102,R0201,R0202,R0203 349 | include-naming-hint = yes 350 | 351 | [pylint.REPORTS] 352 | output-format = text 353 | files-output = no 354 | reports = yes 355 | evaluation = 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 356 | 357 | [pylint.BASIC] 358 | good-names = i,j,k,ex,Run,_ 359 | bad-names = foo,bar,baz,toto,tutu,tata 360 | name-group = 361 | include-naming-hint = no 362 | property-classes = abc.abstractproperty 363 | const-rgx = (([A-Z_][A-Z0-9_]*)|(__.*__))$ 364 | const-name-hint = (([A-Z_][A-Z0-9_]*)|(__.*__))$ 365 | class-rgx = [A-Z_][a-zA-Z0-9]+$ 366 | class-name-hint = [A-Z_][a-zA-Z0-9]+$ 367 | argument-rgx = [a-z_][a-z0-9_]{2,30}$ 368 | argument-name-hint = [a-z_][a-z0-9_]{2,30}$ 369 | variable-rgx = [a-z_][a-z0-9_]{2,30}$ 370 | variable-name-hint = [a-z_][a-z0-9_]{2,30}$ 371 | class-attribute-rgx = ([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 372 | class-attribute-name-hint = ([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 373 | method-rgx = [a-z_][a-z0-9_]{2,30}$ 374 | method-name-hint = [a-z_][a-z0-9_]{2,30}$ 375 | module-rgx = (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 376 | module-name-hint = (([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 377 | function-rgx = [a-z_][a-z0-9_]{2,30}$ 378 | function-name-hint = [a-z_][a-z0-9_]{2,30}$ 379 | attr-rgx = [a-z_][a-z0-9_]{2,30}$ 380 | attr-name-hint = [a-z_][a-z0-9_]{2,30}$ 381 | inlinevar-rgx = [A-Za-z_][A-Za-z0-9_]*$ 382 | inlinevar-name-hint = [A-Za-z_][A-Za-z0-9_]*$ 383 | no-docstring-rgx = ^_ 384 | docstring-min-length = -1 385 | 386 | [pylint.ELIF] 387 | max-nested-blocks = 5 388 | 389 | [pylint.FORMAT] 390 | max-line-length = 88 391 | ignore-long-lines = ^\s*(# )??$ 392 | single-line-if-stmt = no 393 | no-space-check = trailing-comma,dict-separator 394 | max-module-lines = 1000 395 | indent-string=' ' 396 | indent-after-paren = 4 397 | expected-line-ending-format = LF 398 | 399 | [pylint.LOGGING] 400 | logging-modules = logging 401 | 402 | [pylint.MISCELLANEOUS] 403 | notes = FIXME,XXX,TODO 404 | 405 | [pylint.SIMILARITIES] 406 | min-similarity-lines = 4 407 | ignore-comments = yes 408 | ignore-docstrings = yes 409 | ignore-imports = no 410 | 411 | [pylint.SPELLING] 412 | spelling-dict = 413 | spelling-ignore-words = 414 | spelling-private-dict-file = 415 | spelling-store-unknown-words = no 416 | 417 | [pylint.STRING_CONSTANT] 418 | check-quote-consistency = yes 419 | check-str-concat-over-line-jumps = yes 420 | 421 | [pylint.TYPECHECK] 422 | ignore-mixin-members = yes 423 | ignored-modules = 424 | ignored-classes = optparse.Values,thread._local,_thread._local 425 | generated-members = 426 | contextmanager-decorators = contextlib.contextmanager 427 | 428 | [pylint.VARIABLES] 429 | init-import = no 430 | dummy-variables-rgx = (_+[a-zA-Z0-9]*?$)|dummy 431 | additional-builtins = 432 | callbacks = cb_,_cb 433 | redefining-builtins-modules = six.moves,future.builtins 434 | 435 | [pylint.CLASSES] 436 | defining-attr-methods = __init__,__new__,setUp 437 | valid-classmethod-first-arg = cls 438 | valid-metaclass-classmethod-first-arg = mcs 439 | exclude-protected = _asdict,_fields,_replace,_source,_make 440 | 441 | [pylint.DESIGN] 442 | max-args = 5 443 | ignored-argument-names = _.* 444 | max-locals = 15 445 | max-returns = 6 446 | max-branches = 12 447 | max-statements = 50 448 | max-parents = 7 449 | max-attributes = 7 450 | min-public-methods = 2 451 | max-public-methods = 20 452 | max-bool-expr = 5 453 | 454 | [pylint.IMPORTS] 455 | deprecated-modules = optparse 456 | import-graph = 457 | ext-import-graph = 458 | int-import-graph = 459 | known-standard-library = 460 | known-third-party = enchant 461 | analyse-fallback-blocks = no 462 | 463 | [pylint.EXCEPTIONS] 464 | overgeneral-exceptions = Exception 465 | 466 | 467 | [tool:pytest] 468 | DJANGO_SETTINGS_MODULE = tests.settings 469 | python_files = tests.py test_*.py *_tests.py 470 | python_classes = 471 | 472 | [autoflake] 473 | check = true 474 | in-place = true 475 | remove-unused-variables = true 476 | ignore-pass-after-docstring = true 477 | remove-all-unused-imports = true 478 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import setuptools 5 | 6 | 7 | if __name__ == "__main__": 8 | setuptools.setup() 9 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /tests/management/commands/test_print-version.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | from io import StringIO 3 | from typing import List 4 | 5 | from django.test import TestCase 6 | from django.core.management import call_command 7 | 8 | 9 | __all__: List[str] = ["PrintVersionManagementCommandTest"] 10 | 11 | 12 | class PrintVersionManagementCommandTest(TestCase): 13 | """Print version management command tests.""" 14 | 15 | def test_handle(self) -> None: 16 | """Must return version to stdout.""" 17 | out = StringIO() 18 | 19 | with contextlib.redirect_stdout(out): 20 | call_command("print-version") 21 | 22 | result = out.getvalue().strip() 23 | 24 | self.assertEqual(first=result, second="1.0.1 (Aug. 24, 1991)") 25 | -------------------------------------------------------------------------------- /tests/settings.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | from datetime import date 4 | from random import SystemRandom 5 | from typing import Dict, List, Union 6 | 7 | 8 | # black magic to use imports from library code 9 | path = pathlib.Path(__file__).absolute() 10 | project = path.parent.parent.parent 11 | sys.path.insert(0, str(project)) 12 | 13 | # secret key 14 | SECRET_KEY: str = "".join( 15 | [ 16 | SystemRandom().choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") 17 | for i in range(50) 18 | ] 19 | ) 20 | 21 | # configure databases 22 | DATABASES: Dict[str, Dict[str, str]] = { 23 | "default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"} 24 | } 25 | 26 | # configure templates 27 | TEMPLATES: List[Dict[str, Union[str, List[str], bool, Dict[str, str]]]] = [ 28 | { 29 | "BACKEND": "django.template.backends.django.DjangoTemplates", 30 | "DIRS": [], 31 | "APP_DIRS": True, 32 | "OPTIONS": {}, 33 | } 34 | ] 35 | 36 | 37 | # add testing related apps 38 | INSTALLED_APPS: List[str] = [ 39 | "django.contrib.auth", 40 | "django.contrib.contenttypes", 41 | "djversion", 42 | ] 43 | 44 | # configure urls 45 | ROOT_URLCONF: str = "djversion.urls" 46 | 47 | # drf settings 48 | REST_FRAMEWORK: Dict[str, List[str]] = { 49 | "DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer"] 50 | } 51 | 52 | 53 | # djversion settings 54 | DJVERSION_VERSION: str = "1.0.1" 55 | DJVERSION_UPDATED: date = date(1991, 8, 24) 56 | DJVERSION_FORMAT_STRING: str = "{version} ({updated})" # noqa: FS003 57 | -------------------------------------------------------------------------------- /tests/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | __all__: List[str] = [] 5 | -------------------------------------------------------------------------------- /tests/templatetags/test_djversion_tags.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from django.test import TestCase 4 | 5 | from djversion.templatetags.djversion_tags import project_version 6 | 7 | 8 | __all__: List[str] = ["ProjectVersionTemplatetagTest"] 9 | 10 | 11 | class ProjectVersionTemplatetagTest(TestCase): 12 | """Project version templatetag tests.""" 13 | 14 | def test_project_version(self) -> None: 15 | """Must return formatted version tag.""" 16 | result: str = project_version() 17 | 18 | self.assertIsInstance(obj=result, cls=str) 19 | self.assertEqual(first=result, second="1.0.1 (Aug. 24, 1991)") 20 | -------------------------------------------------------------------------------- /tests/test_context_processors.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List 2 | 3 | from django.test import TestCase 4 | from django.http import HttpRequest 5 | 6 | from djversion.context_processors import version 7 | 8 | 9 | __all__: List[str] = ["VersionContextProcessorTest"] 10 | 11 | 12 | class VersionContextProcessorTest(TestCase): 13 | """Version context processor tests.""" 14 | 15 | def test_version(self) -> None: 16 | """Must return formatted new context variable with version.""" 17 | request: HttpRequest = HttpRequest() 18 | result: Dict[str, str] = version(request=request) 19 | 20 | self.assertIsInstance(obj=result, cls=dict) 21 | self.assertDictEqual(d1=result, d2={"VERSION": "1.0.1 (Aug. 24, 1991)"}) 22 | -------------------------------------------------------------------------------- /tests/test_rest.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from django.test import TestCase 4 | from django.http import HttpRequest 5 | from rest_framework.response import Response 6 | 7 | from djversion.rest import VersionView 8 | 9 | 10 | __all__: List[str] = ["VersionViewTest"] 11 | 12 | 13 | class VersionViewTest(TestCase): 14 | """Version REST view tests.""" 15 | 16 | def test_get(self) -> None: 17 | """Method must return response containing version.""" 18 | request: HttpRequest = HttpRequest() 19 | request.method = "GET" 20 | 21 | view = VersionView().as_view() 22 | result: Response = view(request=request) 23 | 24 | self.assertDictEqual(d1=result.data, d2={"version": "1.0.1 (Aug. 24, 1991)"}) 25 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | from typing import List 3 | from pathlib import Path 4 | 5 | import git 6 | from django.test import TestCase 7 | from django.test.utils import override_settings 8 | from django.utils.translation import override as override_translation 9 | 10 | from djversion.conf import settings 11 | from djversion.utils import get_version 12 | 13 | 14 | __all__: List[str] = ["GetVersionUtilTest"] 15 | 16 | 17 | class GetVersionUtilTest(TestCase): 18 | """get_version util tests.""" 19 | 20 | def test_get_version(self) -> None: 21 | """Util must return current version and updated date formatted using format string.""" # noqa: E501 22 | self.assertEqual(first=get_version(), second="1.0.1 (Aug. 24, 1991)") 23 | 24 | @override_settings(DJVERSION_FORMAT_STRING="{updated}: {version}") # noqa: FS003 25 | @override_translation(language="en") 26 | def test_get_version__with_custom_format_string(self) -> None: 27 | """Util must return current version and updated date formatted using custom format string.""" # noqa: E501 28 | self.assertEqual(first=get_version(), second="Aug. 24, 1991: 1.0.1") 29 | 30 | @override_settings(DJVERSION_UPDATED=None) 31 | @override_translation(language="en") 32 | def test_get_version__without_updated(self) -> None: 33 | """Util must return current version.""" 34 | self.assertEqual(first=get_version(), second="1.0.1") 35 | 36 | @override_settings(DJVERSION_VERSION=None) 37 | @override_translation(language="en") 38 | def test_get_version__without_version(self) -> None: 39 | """Util must return updated.""" 40 | self.assertEqual(first=get_version(), second="Aug. 24, 1991") 41 | 42 | @override_settings(DJVERSION_VERSION=None, DJVERSION_UPDATED=None) 43 | @override_translation(language="en") 44 | def test_get_version__without_settings(self) -> None: 45 | """Util must return empty string.""" 46 | self.assertEqual(first=get_version(), second="") 47 | 48 | @override_settings( 49 | DJVERSION_VERSION=None, 50 | DJVERSION_UPDATED=None, 51 | DJVERSION_GIT_REPO_PATH="./tmp", 52 | DJVERSION_GIT_USE_TAG=True, 53 | ) 54 | def test_get_version__with_git_tag(self) -> None: 55 | """Util must return current tag from git repo from path.""" 56 | path = Path(settings.DJVERSION_GIT_REPO_PATH) # type: ignore 57 | test: Path = path.joinpath("TEST") 58 | repo: git.Repo = git.Repo.init(str(path.absolute())) 59 | with repo.config_writer() as config: 60 | config.set_value(section="user", option="name", value="TEST") 61 | config.set_value(section="user", option="email", value="test@example.com") 62 | config.write() 63 | config.release() 64 | author: git.Actor = git.Actor(name="TEST", email="test@example.com") 65 | committer: git.Actor = git.Actor(name="TEST", email="test@example.com") 66 | test.absolute().open("wb").close() 67 | repo.index.add([str(test.absolute())]) 68 | repo.index.commit(message="TEST", author=author, committer=committer) 69 | repo.create_tag("0.0.1", message="v0.0.1") 70 | version: str = get_version() 71 | shutil.rmtree(path) 72 | 73 | self.assertEqual(first=version, second="0.0.1") 74 | 75 | @override_settings( 76 | DJVERSION_VERSION=None, 77 | DJVERSION_UPDATED=None, 78 | DJVERSION_GIT_REPO_PATH="./tmp", 79 | DJVERSION_GIT_USE_COMMIT=True, 80 | ) 81 | def test_get_version__with_git_commit(self) -> None: 82 | """Util must return last commit from git repo from path.""" 83 | path = Path(settings.DJVERSION_GIT_REPO_PATH) # type: ignore 84 | test: Path = path.joinpath("TEST") 85 | repo: git.Repo = git.Repo.init(str(path.absolute())) 86 | with repo.config_writer() as config: 87 | config.set_value(section="user", option="name", value="TEST") 88 | config.set_value(section="user", option="email", value="test@example.com") 89 | config.write() 90 | config.release() 91 | author: git.Actor = git.Actor(name="TEST", email="test@example.com") 92 | committer: git.Actor = git.Actor(name="TEST", email="test@example.com") 93 | test.absolute().open("wb").close() 94 | repo.index.add([str(test.absolute())]) 95 | commit = repo.index.commit( 96 | message="TEST", author=author, committer=committer 97 | ) 98 | version: str = get_version() 99 | shutil.rmtree(path) 100 | 101 | self.assertEqual(first=version, second=commit.hexsha) 102 | --------------------------------------------------------------------------------