Remove pytest -> use normal unittest

This commit is contained in:
Jens Diemer 2023-11-26 13:41:54 +01:00
parent 884d202f44
commit d0ea014984
20 changed files with 576 additions and 732 deletions

View file

@ -1,65 +0,0 @@
SHELL := /bin/bash
MAX_LINE_LENGTH := 100
all: help
help:
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9 -]+:.*?## / {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
check-poetry:
@if [[ "$(shell poetry --version 2>/dev/null)" == *"Poetry"* ]] ; \
then \
echo "Poetry found, ok." ; \
else \
echo 'Please install poetry first, with e.g.:' ; \
echo 'make install-poetry' ; \
exit 1 ; \
fi
install-base-req: ## Install needed base packages via apt
sudo apt install python3-pip python3-venv
install-poetry: ## install or update poetry
curl -sSL https://install.python-poetry.org | python3 -
install: check-poetry ## install project via poetry
python3 -m venv .venv
poetry install
update: check-poetry ## update the sources and installation and generate "conf/requirements.txt"
python3 -m venv .venv
poetry self update
poetry update -v
poetry install
poetry export -f requirements.txt --output conf/requirements.txt
lint: ## Run code formatters and linter
poetry run darker --check
poetry run isort --check-only .
poetry run flake8 .
fix-code-style: ## Fix code formatting
poetry run darker
poetry run isort .
tox-listenvs: check-poetry ## List all tox test environments
poetry run tox --listenvs
tox: check-poetry ## Run pytest via tox with all environments
poetry run tox
pytest: install ## Run pytest
poetry run pytest
local-test: install ## Run local_test.py to run the project locally
poetry run python3 ./local_test.py
local-diff-settings: ## Run "manage.py diffsettings" with local test
poetry run python3 local_test/opt_yunohost/manage.py diffsettings
safety: ## Run https://github.com/pyupio/safety
poetry run safety check --full-report
##############################################################################
.PHONY: help check-poetry install-poetry install update local-test

View file

@ -46,24 +46,12 @@ e.g.:
```bash ```bash
~$ git clone https://github.com/YunoHost-Apps/django_example.git ~$ git clone https://github.com/YunoHost-Apps/django_example.git
~$ cd django_example_ynh/ ~$ cd django_example_ynh/
~/django_example$ make ~/django_example$ ./dev-cli.py --help
install-poetry install or update poetry
install install project via poetry
update update the sources and installation and generate "conf/requirements.txt"
lint Run code formatters and linter
fix-code-style Fix code formatting
tox-listenvs List all tox test environments
tox Run pytest via tox with all environments
pytest Run pytest
publish Release new version to PyPi
local-test Run local_test.py to run the project locally
local-diff-settings Run "manage.py diffsettings" with local test
~/django_example$ make install-poetry
~/django_example$ make install
~/django_example$ make local-test
``` ```
Notes: Notes:
* SQlite database will be used * SQlite database will be used

View file

@ -1,71 +1,132 @@
asgiref==3.7.2 ; python_version >= "3.9" and python_version < "4" \ #
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# ./dev-cli.py update
#
asgiref==3.7.2 \
--hash=sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e \ --hash=sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e \
--hash=sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed --hash=sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed
async-timeout==4.0.3 ; python_version >= "3.9" and python_full_version <= "3.11.2" \ # via django
async-timeout==4.0.3 \
--hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \
--hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028
bleach==6.0.0 ; python_version >= "3.9" and python_version < "4" \ # via
--hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ # django-example-ynh (pyproject.toml)
--hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 # redis
bx-django-utils==64 ; python_version >= "3.9" and python_full_version < "4.0.0" \ bleach==6.1.0 \
--hash=sha256:55e920caf2f1fda4f5b199d48558d1e8a8f2408a244833be205e6c4083610906 \ --hash=sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe \
--hash=sha256:a89c5b6dd13e8ee28b13c315dce28ff5ad0e6637281ef16754cecf32537b5b4f --hash=sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6
bx-py-utils==85 ; python_version >= "3.9" and python_version < "4" \ # via django-tools
--hash=sha256:8d6ee4bb0c431304b812f5bebb1bc8e2ab05f1b6c2f8d16d352cbcee5e916cd2 \ bx-django-utils==69 \
--hash=sha256:df023fa05cda8e969d2cbdb4cc348d8b7670567a2fe775faf7a0c869ec56eaa2 --hash=sha256:39e96b8ad47bcf36d6713e4e42c8d09deb21e413160dc2944f17b7d2e2244713 \
colorama==0.4.6 ; python_version >= "3.9" and python_version < "4" and sys_platform == "win32" \ --hash=sha256:59b806aa36b50184f14bd0f7a61fb66c478fa231a44f92472360ce0cf1616013
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ # via django-example
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 bx-py-utils==88 \
colorlog==6.7.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:32fbc7e9ff3dfb0a817c80fb1d165ec559643dab59c0be549e646acbf8223b75 \
--hash=sha256:3a6f4eeef6abcac834b2c1ea4c5211130fd930a064aa0baabddd7c2bd00e38ac
# via
# bx-django-utils
# cli-base-utilities
# django-tools
cli-base-utilities==0.4.4 \
--hash=sha256:110bef895fb7dfc29662f463ccedc4c985a880afbde2e6dea387d0d2f96f4985 \
--hash=sha256:72d4248776519a21c3448d6e348511ce6fe8c3742c154e158473236c8278fb1c
# via django-example-ynh (pyproject.toml)
click==8.1.7 \
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
# via
# cli-base-utilities
# rich-click
colorlog==6.7.0 \
--hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \
--hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5
django-axes==6.1.0 ; python_version >= "3.9" and python_version < "4" \ # via django-yunohost-integration
--hash=sha256:a7d509dc76e67440839522a182dc63ecafc3bac3af9de6f263d2bcec1154e50e \ django==4.2.7 \
--hash=sha256:e3d44d4ec64ba6d470ef01b6c4b53b6b3747de96821f7c0ef96c64bffa9f6f74 --hash=sha256:8e0f1c2c2786b5c0e39fe1afce24c926040fad47c8ea8ad30aaf1188df29fc41 \
django-example==0.2.0 ; python_version >= "3.9" and python_full_version < "4.0.0" \ --hash=sha256:e1d37c51ad26186de355cbcec16613ebdabfa9689bbade9c538835205a8abbe9
# via
# bx-django-utils
# django-axes
# django-redis
# django-tools
# django-yunohost-integration
django-axes==6.1.1 \
--hash=sha256:29c48ff5f09046afd5e9a16e96d3bbb79f6c11c59f0a7bbd732559e60d0aa9fa \
--hash=sha256:cd1bc4f7becc8e9243eb4090dffa258d7d7125ca0ce3153b6ffc920bccbf2c3f
# via django-yunohost-integration
django-example==0.2.0 \
--hash=sha256:2bcaeed97868e8be5c4d7d6a745b054f6983c931d5cefb763e6ff25807f15793 \ --hash=sha256:2bcaeed97868e8be5c4d7d6a745b054f6983c931d5cefb763e6ff25807f15793 \
--hash=sha256:469beaa9e4f3e5d0ee98f043ee533f0f01fafef128391ac9f4ca9d9f35290da0 --hash=sha256:469beaa9e4f3e5d0ee98f043ee533f0f01fafef128391ac9f4ca9d9f35290da0
django-redis==5.3.0 ; python_version >= "3.9" and python_version < "4" \ # via django-example-ynh (pyproject.toml)
--hash=sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac \ django-redis==5.4.0 \
--hash=sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44 --hash=sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42 \
django-tools==0.54.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b
# via django-yunohost-integration
django-tools==0.54.0 \
--hash=sha256:5040a91282be9d1c9d379b0c65da50bcb3691bff03cee54fd4123ace238c3a43 \ --hash=sha256:5040a91282be9d1c9d379b0c65da50bcb3691bff03cee54fd4123ace238c3a43 \
--hash=sha256:a7b7bfa5b9c5a81966454d17dffb2403cee25a806c858ee0486a08798227598f --hash=sha256:a7b7bfa5b9c5a81966454d17dffb2403cee25a806c858ee0486a08798227598f
django-yunohost-integration[ynh]==0.6.0 ; python_version >= "3.9" and python_version < "4" \ # via django-yunohost-integration
django-yunohost-integration[ynh]==0.6.0 \
--hash=sha256:9596ab56b66edf1b56eccaceb4b5807df237e752128e79568cd13b075267f26f \ --hash=sha256:9596ab56b66edf1b56eccaceb4b5807df237e752128e79568cd13b075267f26f \
--hash=sha256:dfb72b94ae30e02948dd60ca76d56da4ca6a74ea04f357b8d61b94807fca0493 --hash=sha256:dfb72b94ae30e02948dd60ca76d56da4ca6a74ea04f357b8d61b94807fca0493
django==4.2.4 ; python_version >= "3.9" and python_version < "4" \ # via
--hash=sha256:7e4225ec065e0f354ccf7349a22d209de09cc1c074832be9eb84c51c1799c432 \ # django-example-ynh (pyproject.toml)
--hash=sha256:860ae6a138a238fc4f22c99b52f3ead982bb4b1aad8c0122bcd8c8a3a02e409d # django-yunohost-integration
gunicorn==21.2.0 ; python_version >= "3.9" and python_version < "4" \ gunicorn==21.2.0 \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \ --hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033 --hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
icdiff==2.0.7 ; python_version >= "3.9" and python_version < "4" \ # via django-yunohost-integration
icdiff==2.0.7 \
--hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \ --hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \
--hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f --hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f
packaging==23.1 ; python_version >= "3.9" and python_version < "4" \ # via django-tools
--hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ markdown-it-py==3.0.0 \
--hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \
pprintpp==0.4.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb
# via rich
mdurl==0.1.2 \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
# via markdown-it-py
packaging==23.2 \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
# via
# django-yunohost-integration
# gunicorn
pprintpp==0.4.0 \
--hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \ --hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \
--hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403 --hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403
psycopg2==2.9.7 ; python_version >= "3.9" and python_version < "4" \ # via django-tools
--hash=sha256:1a6a2d609bce44f78af4556bea0c62a5e7f05c23e5ea9c599e07678995609084 \ psycopg2==2.9.9 \
--hash=sha256:44d93a0109dfdf22fe399b419bcd7fa589d86895d3931b01fb321d74dadc68f1 \ --hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \
--hash=sha256:8275abf628c6dc7ec834ea63f6f3846bf33518907a2b9b693d41fd063767a866 \ --hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \
--hash=sha256:91e81a8333a0037babfc9fe6d11e997a9d4dac0f38c43074886b0d9dead94fe9 \ --hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \
--hash=sha256:b22ed9c66da2589a664e0f1ca2465c29b75aaab36fa209d4fb916025fb9119e5 \ --hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \
--hash=sha256:b6bd7d9d3a7a63faae6edf365f0ed0e9b0a1aaf1da3ca146e6b043fb3eb5d723 \ --hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \
--hash=sha256:c7949770cafbd2f12cecc97dea410c514368908a103acf519f2a346134caa4d5 \ --hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \
--hash=sha256:d1210fcf99aae6f728812d1d2240afc1dc44b9e6cba526a06fb8134f969957c2 \ --hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \
--hash=sha256:d5c5297e2fbc8068d4255f1e606bfc9291f06f91ec31b2a0d4c536210ac5c0a2 \ --hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \
--hash=sha256:e9b04cbef584310a1ac0f0d55bb623ca3244c87c51187645432e342de9ae81a8 \ --hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \
--hash=sha256:f00cc35bd7119f1fed17b85bd1007855194dde2cbd8de01ab8ebb17487440ad8 --hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \
python-stdnum==1.19 ; python_version >= "3.9" and python_full_version < "4.0.0" \ --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \
--hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \
--hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c
# via django-yunohost-integration
pygments==2.17.2 \
--hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \
--hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367
# via rich
python-stdnum==1.19 \
--hash=sha256:133ec82f56390ea74c190569e98f2fb14b869808b1d54785708f22d0fead8b3f \ --hash=sha256:133ec82f56390ea74c190569e98f2fb14b869808b1d54785708f22d0fead8b3f \
--hash=sha256:1b5b401ad3f45b798b0317313b781a433f5d7a5ff2c9feb8054664f76f78644e --hash=sha256:1b5b401ad3f45b798b0317313b781a433f5d7a5ff2c9feb8054664f76f78644e
pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" \ # via bx-django-utils
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
--hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
--hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
@ -73,7 +134,10 @@ pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
--hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
--hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
--hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
--hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
--hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
--hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
@ -81,9 +145,12 @@ pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
--hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
--hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
@ -98,31 +165,55 @@ pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
--hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
--hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
--hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
--hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
redis==5.0.0 ; python_version >= "3.9" and python_version < "4" \ # via django-yunohost-integration
--hash=sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0 \ redis==5.0.1 \
--hash=sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120 --hash=sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f \
setuptools==68.1.2 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f
--hash=sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d \ # via django-redis
--hash=sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b rich==13.7.0 \
six==1.16.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa \
--hash=sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235
# via
# cli-base-utilities
# rich-click
rich-click==1.7.1 \
--hash=sha256:660c8ea345343f47c5de88f62afa34a19d9f4c7accdd9c6e39dc17eece6affcd \
--hash=sha256:c37d19af85c86b9a256c18e9d23637ae89478300ec8dc5e220c6ca213675f2f9
# via cli-base-utilities
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
sqlparse==0.4.4 ; python_version >= "3.9" and python_version < "4" \ # via bleach
sqlparse==0.4.4 \
--hash=sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3 \ --hash=sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3 \
--hash=sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c --hash=sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c
typing-extensions==4.7.1 ; python_version >= "3.9" and python_version < "3.11" \ # via django
--hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ tomlkit==0.12.3 \
--hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 --hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \
tzdata==2023.3 ; python_version >= "3.9" and python_version < "4" and sys_platform == "win32" \ --hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba
--hash=sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a \ # via cli-base-utilities
--hash=sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda typing-extensions==4.8.0 \
webencodings==0.5.1 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \
--hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef
# via
# asgiref
# rich-click
webencodings==0.5.1 \
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
# via bleach
# The following packages are considered to be unsafe in a requirements file:
setuptools==69.0.2 \
--hash=sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2 \
--hash=sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6
# via django-axes

View file

@ -9,6 +9,7 @@
################################################################################ ################################################################################
################################################################################ ################################################################################
from pathlib import Path as __Path from pathlib import Path as __Path
from django_yunohost_integration.base_settings import * # noqa:F401,F403 from django_yunohost_integration.base_settings import * # noqa:F401,F403
@ -59,9 +60,7 @@ if 'axes' not in INSTALLED_APPS:
INSTALLED_APPS.append('django_yunohost_integration.apps.YunohostIntegrationConfig') INSTALLED_APPS.append('django_yunohost_integration.apps.YunohostIntegrationConfig')
SECRET_KEY = __get_or_create_secret( SECRET_KEY = __get_or_create_secret(DATA_DIR_PATH / 'secret.txt') # /home/yunohost.app/$app/secret.txt
DATA_DIR_PATH / 'secret.txt'
) # /home/yunohost.app/$app/secret.txt
MIDDLEWARE.insert( MIDDLEWARE.insert(

View file

@ -3,5 +3,5 @@
Demo YunoHost Application to demonstrate the integration of a Django project under YunoHost. Demo YunoHost Application to demonstrate the integration of a Django project under YunoHost.
""" """
__version__ = '0.1.0rc0+ynh1' __version__ = '0.2.0+ynh3'
__author__ = 'Jens Diemer <django_example_ynh@jensdiemer.de>' __author__ = 'Jens Diemer <django_example_ynh@jensdiemer.de>'

View file

@ -2,16 +2,19 @@
CLI for development CLI for development
""" """
import logging import logging
import os
import sys import sys
from pathlib import Path from pathlib import Path
import django
import rich_click as click import rich_click as click
from bx_py_utils.path import assert_is_file from bx_py_utils.path import assert_is_file
from django_yunohost_integration.local_test import create_local_test
from manageprojects.utilities import code_style
from manageprojects.utilities.publish import publish_package
from cli_base.cli_tools.subprocess_utils import verbose_check_call from cli_base.cli_tools.subprocess_utils import verbose_check_call
from cli_base.cli_tools.version_info import print_version from cli_base.cli_tools.version_info import print_version
from django.core.management.commands.test import Command as DjangoTestCommand
from django_yunohost_integration.local_test import CreateResults, create_local_test
from manageprojects.utilities import code_style
from manageprojects.utilities.publish import publish_package
from rich import print # noqa; noqa from rich import print # noqa; noqa
from rich_click import RichGroup from rich_click import RichGroup
@ -42,6 +45,7 @@ ARGUMENT_NOT_EXISTING_DIR = dict(
ARGUMENT_EXISTING_FILE = dict( ARGUMENT_EXISTING_FILE = dict(
type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True, path_type=Path) type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True, path_type=Path)
) )
CLI_EPILOG = 'Project Homepage: https://github.com/YunoHost-Apps/django_example_ynh'
class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier? class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier?
@ -50,10 +54,7 @@ class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier?
return super().make_context(info_name, *args, **kwargs) return super().make_context(info_name, *args, **kwargs)
@click.group( @click.group(cls=ClickGroup, epilog=CLI_EPILOG)
cls=ClickGroup,
epilog='Project Homepage: https://github.com/YunoHost-Apps/django_example_ynh',
)
def cli(): def cli():
pass pass
@ -76,7 +77,7 @@ def coverage(verbose: bool = True):
""" """
verbose_check_call('coverage', 'run', verbose=verbose, exit_on_error=True) verbose_check_call('coverage', 'run', verbose=verbose, exit_on_error=True)
verbose_check_call('coverage', 'combine', '--append', verbose=verbose, exit_on_error=True) verbose_check_call('coverage', 'combine', '--append', verbose=verbose, exit_on_error=True)
verbose_check_call('coverage', 'report', '--fail-under=30', verbose=verbose, exit_on_error=True) verbose_check_call('coverage', 'report', '--fail-under=10', verbose=verbose, exit_on_error=True)
verbose_check_call('coverage', 'xml', verbose=verbose, exit_on_error=True) verbose_check_call('coverage', 'xml', verbose=verbose, exit_on_error=True)
verbose_check_call('coverage', 'json', verbose=verbose, exit_on_error=True) verbose_check_call('coverage', 'json', verbose=verbose, exit_on_error=True)
@ -163,7 +164,10 @@ def publish():
""" """
Build and upload this project to PyPi Build and upload this project to PyPi
""" """
_run_unittest_cli(verbose=False, exit_after_run=False) # Don't publish a broken state try:
_run_django_test_cli() # Don't publish a broken state
except SystemExit as err:
assert err.code == 0, f'Exit code is not 0: {err.code}'
publish_package( publish_package(
module=django_example_ynh, module=django_example_ynh,
@ -217,64 +221,59 @@ def update_test_snapshot_files():
print(f'{removed_file_count} test snapshot files removed... run tests...') print(f'{removed_file_count} test snapshot files removed... run tests...')
# Just recreate them by running tests: # Just recreate them by running tests:
_run_unittest_cli( os.environ['RAISE_SNAPSHOT_ERRORS'] = '0' # Recreate snapshot files without error
extra_env=dict( try:
RAISE_SNAPSHOT_ERRORS='0', # Recreate snapshot files without error _run_django_test_cli()
), finally:
verbose=False, new_files = len(list(iter_snapshot_files()))
exit_after_run=False, print(f'{new_files} test snapshot files created, ok.\n')
)
new_files = len(list(iter_snapshot_files()))
print(f'{new_files} test snapshot files created, ok.\n')
cli.add_command(update_test_snapshot_files) cli.add_command(update_test_snapshot_files)
def _run_unittest_cli(extra_env=None, verbose=True, exit_after_run=True): def _run_django_test_cli():
""" """
Call the origin unittest CLI and pass all args to it. Call the origin Django test manage command CLI and pass all args to it.
""" """
if extra_env is None: os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
extra_env = dict()
extra_env.update( print('Compile YunoHost files...')
dict( result: CreateResults = create_local_test(
PYTHONUNBUFFERED='1', django_settings_path=PACKAGE_ROOT / 'conf' / 'settings.py',
PYTHONWARNINGS='always', destination=PACKAGE_ROOT / 'local_test',
) runserver=False,
extra_replacements={
'__DEBUG_ENABLED__': '0', # "1" or "0" string
'__LOG_LEVEL__': 'INFO',
'__ADMIN_EMAIL__': 'foo-bar@test.tld',
'__DEFAULT_FROM_EMAIL__': 'django_app@test.tld',
},
) )
print('Local test files created:')
print(result)
args = sys.argv[2:] data_dir = str(result.data_dir_path)
if not args: if data_dir not in sys.path:
if verbose: sys.path.insert(0, data_dir)
args = ('--verbose', '--locals', '--buffer')
else:
args = ('--locals', '--buffer')
verbose_check_call( django.setup()
sys.executable,
'-m', os.chdir(Path(django_example_ynh.__file__).parent)
'unittest',
*args, test_command = DjangoTestCommand()
timeout=15 * 60, test_command.run_from_argv(sys.argv)
extra_env=extra_env,
)
if exit_after_run:
sys.exit(0)
@click.command() # Dummy command @click.command() # Dummy command
def test(): def test():
""" """
Run unittests Compile YunoHost files and run Django unittests
""" """
_run_unittest_cli() _run_django_test_cli()
# TODO: Replace pytest with normal Django unittests: cli.add_command(test)
# cli.add_command(test)
def _run_tox(): def _run_tox():
@ -290,7 +289,7 @@ def tox():
_run_tox() _run_tox()
# TODO: cli.add_command(tox) cli.add_command(tox)
@click.command() @click.command()
@ -347,30 +346,19 @@ def diffsettings():
cli.add_command(diffsettings) cli.add_command(diffsettings)
@click.command()
def pytest():
"""
Run tests via "pytest"
"""
verbose_check_call(
sys.executable, '-m', 'pytest', *sys.argv[2:], cwd=PACKAGE_ROOT
)
cli.add_command(pytest)
def main(): def main():
print_version(django_example_ynh) print_version(django_example_ynh)
print(f'{sys.argv=}')
if len(sys.argv) >= 2: if len(sys.argv) >= 2:
# Check if we just pass a command call # Check if we just pass a command call
command = sys.argv[1] command = sys.argv[1]
if command == 'test': if command == 'test':
_run_unittest_cli() _run_django_test_cli()
sys.exit(0)
elif command == 'tox': elif command == 'tox':
_run_tox() _run_tox()
sys.exit(0)
# Execute Click CLI: print('Execute Click CLI')
cli() cli()

View file

@ -0,0 +1,109 @@
<div id="container">
<!-- Header -->
<div id="header">
<div id="branding">
<h1 id="site-name">
<a href="/app_path/admin/">
Django administration
</a>
</h1>
</div>
<div id="user-tools">
Welcome,
<strong>
test
</strong>
.
<a href="/">
View site
</a>
/
<a href="/app_path/admin/password_change/">
Change password
</a>
/
<form action="/app_path/admin/logout/" id="logout-form" method="post">
MockedCsrfTokenNode
<button type="submit">
Log out
</button>
</form>
<button class="theme-toggle">
<div class="visually-hidden theme-label-when-auto">
Toggle theme (current theme: auto)
</div>
<div class="visually-hidden theme-label-when-light">
Toggle theme (current theme: light)
</div>
<div class="visually-hidden theme-label-when-dark">
Toggle theme (current theme: dark)
</div>
<svg aria-hidden="true" class="theme-icon-when-auto">
<use xlink:href="#icon-auto">
</use>
</svg>
<svg aria-hidden="true" class="theme-icon-when-dark">
<use xlink:href="#icon-moon">
</use>
</svg>
<svg aria-hidden="true" class="theme-icon-when-light">
<use xlink:href="#icon-sun">
</use>
</svg>
</button>
</div>
</div>
<!-- END Header -->
<div class="main" id="main">
<div class="content" id="content-start" tabindex="-1">
<!-- Content -->
<div class="colMS" id="content">
<h1>
Site administration
</h1>
<div id="content-main">
<div class="app-yunohost-django-example-project module">
<table>
<caption>
<a class="section" href="" title="Models in the YunoHost Django Example Project application">
YunoHost Django Example Project
</a>
</caption>
<tr class="model-">
<th scope="row">
<a href="/app_path/admin/yunohost-django-example-project/go-to-example-project-debug-view/">
Go to Example Project Debug View
</a>
</th>
<td>
</td>
<td>
<a class="viewlink" href="/app_path/admin/yunohost-django-example-project/go-to-example-project-debug-view/">
View
</a>
</td>
</tr>
</table>
</div>
</div>
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>
Recent actions
</h2>
<h3>
My actions
</h3>
<p>
None available
</p>
</div>
</div>
<br class="clear"/>
</div>
<!-- END Content -->
<div id="footer">
</div>
</div>
</div>
</div>

View file

@ -1,68 +1,104 @@
import subprocess import os
from unittest import TestCase
from bx_py_utils.path import assert_is_file
from manageprojects.test_utils.click_cli_utils import subprocess_cli
from manageprojects.test_utils.project_setup import check_editor_config, get_py_max_line_length
from manageprojects.utilities import code_style
from packaging.version import Version
from django_example_ynh import __version__
from django_example_ynh.cli.dev import PACKAGE_ROOT from django_example_ynh.cli.dev import PACKAGE_ROOT
try:
import tomllib # New in Python 3.11
except ImportError:
import tomli as tomllib
from bx_django_utils.filename import clean_filename
from bx_py_utils.path import assert_is_dir, assert_is_file
from django.test.testcases import TestCase
from django_tools.unittest_utils.project_setup import check_editor_config
from django_yunohost_integration.test_utils import assert_project_version
from django_example import __version__ as upstream_version
from django_example_ynh import __version__ as ynh_pkg_version
def assert_file_contains_string(file_path, string):
with file_path.open('r') as f:
for line in f:
if string in line:
return
raise AssertionError(f'File {file_path} does not contain {string!r} !')
class ProjectSetupTestCase(TestCase): class ProjectSetupTestCase(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
manifest_path = PACKAGE_ROOT / 'manifest.toml'
assert_is_file(manifest_path)
cls.manifest_cfg = tomllib.loads(manifest_path.read_text(encoding='UTF-8'))
def test_version(self): def test_version(self):
self.assertIsNotNone(__version__) assert ynh_pkg_version.startswith(
upstream_version
), f'{ynh_pkg_version=} does not start with {upstream_version=}'
self.assertIn('+ynh', ynh_pkg_version)
version = Version(__version__) # Will raise InvalidVersion() if wrong formatted # pyproject.toml needs a PEP 440 conform version and used "+ynh"
self.assertEqual(str(version), __version__) # the YunoHost syntax is: "~ynh", just "convert this:
manifest_version = ynh_pkg_version.replace('+', '~')
self.assertEqual(self.manifest_cfg['version'], manifest_version)
dev_cli_bin = PACKAGE_ROOT / 'dev-cli.py' if 'GITHUB_ACTION' not in os.environ:
assert_is_file(dev_cli_bin) # Github has a rate-limiting... So don't fetch the API if we run as GitHub action
assert_project_version(
output = subprocess.check_output([dev_cli_bin, 'version'], text=True) current_version=ynh_pkg_version,
self.assertIn(f'django_example_ynh v{__version__}', output) github_project_url='https://github.com/jedie/django-example',
def test_code_style(self):
dev_cli_bin = PACKAGE_ROOT / 'dev-cli.py'
assert_is_file(dev_cli_bin)
try:
output = subprocess_cli(
cli_bin=dev_cli_bin,
args=('check-code-style',),
exit_on_error=False,
) )
except subprocess.CalledProcessError as err:
self.assertIn('.venv/bin/darker', err.stdout) # darker was called?
else:
if 'Code style: OK' in output:
self.assertIn('.venv/bin/darker', output) # darker was called?
return # Nothing to fix -> OK
# Try to "auto" fix code style: def test_screenshot_filenames(self):
"""
try: https://forum.yunohost.org/t/yunohost-bot-cant-handle-spaces-in-screenshots/19483
output = subprocess_cli( """
cli_bin=dev_cli_bin, screenshot_path = PACKAGE_ROOT / 'doc' / 'screenshots'
args=('fix-code-style',), assert_is_dir(screenshot_path)
exit_on_error=False, renamed = []
) for file_path in screenshot_path.iterdir():
except subprocess.CalledProcessError as err: file_name = file_path.name
output = err.stdout if file_name.startswith('.'):
continue
self.assertIn('.venv/bin/darker', output) # darker was called? cleaned_name = clean_filename(file_name)
if cleaned_name != file_name:
# Check again and display the output: new_path = file_path.with_name(cleaned_name)
file_path.rename(new_path)
try: renamed.append(f'{file_name!r} renamed to {cleaned_name!r}')
code_style.check(package_root=PACKAGE_ROOT) assert not renamed, f'Bad screenshots file names found: {", ".join(renamed)}'
except SystemExit as err:
self.assertEqual(err.code, 0, 'Code style error, see output above!')
def test_check_editor_config(self): def test_check_editor_config(self):
check_editor_config(package_root=PACKAGE_ROOT) check_editor_config(package_root=PACKAGE_ROOT)
max_line_length = get_py_max_line_length(package_root=PACKAGE_ROOT) def test_manifest_toml(self):
self.assertEqual(max_line_length, 119) self.assertEqual(self.manifest_cfg['packaging_format'], 2)
self.assertEqual(
set(self.manifest_cfg['install'].keys()),
{
'admin',
'admin_email',
'debug_enabled',
'default_from_email',
'domain',
'init_main_permission',
'log_level',
'path',
},
)
self.assertEqual(
set(self.manifest_cfg['resources'].keys()),
{
'apt',
'data_dir',
'database',
'install_dir',
'permissions',
'ports',
'system_user',
},
)

View file

@ -0,0 +1,36 @@
from pathlib import Path
from bx_py_utils.auto_doc import assert_readme_block
from manageprojects.test_utils.click_cli_utils import invoke_click
from manageprojects.tests.base import BaseTestCase
from django_example_ynh.cli.dev import CLI_EPILOG, PACKAGE_ROOT, cli
def assert_cli_help_in_readme(text_block: str, marker: str, readme_path: Path):
text_block = text_block.replace(CLI_EPILOG, '')
text_block = f'```\n{text_block.strip()}\n```'
assert_readme_block(
readme_path=readme_path,
text_block=text_block,
start_marker_line=f'[comment]: <> (✂✂✂ auto generated {marker} start ✂✂✂)',
end_marker_line=f'[comment]: <> (✂✂✂ auto generated {marker} end ✂✂✂)',
)
class ReadmeTestCase(BaseTestCase):
def test_main_help(self):
stdout = invoke_click(cli, '--help')
self.assert_in_content(
got=stdout,
parts=(
'Usage: ./dev-cli.py [OPTIONS] COMMAND [ARGS]...',
' local-test ',
CLI_EPILOG,
),
)
assert_cli_help_in_readme(
text_block=stdout,
marker='help',
readme_path=PACKAGE_ROOT / 'doc' / 'ADMIN.md',
)

View file

@ -37,24 +37,42 @@ e.g.:
```bash ```bash
~$ git clone https://github.com/YunoHost-Apps/django_example.git ~$ git clone https://github.com/YunoHost-Apps/django_example.git
~$ cd django_example_ynh/ ~$ cd django_example_ynh/
~/django_example$ make ~/django_example$ ./dev-cli.py --help
install-poetry install or update poetry
install install project via poetry
update update the sources and installation and generate "conf/requirements.txt"
lint Run code formatters and linter
fix-code-style Fix code formatting
tox-listenvs List all tox test environments
tox Run pytest via tox with all environments
pytest Run pytest
publish Release new version to PyPi
local-test Run local_test.py to run the project locally
local-diff-settings Run "manage.py diffsettings" with local test
~/django_example$ make install-poetry
~/django_example$ make install
~/django_example$ make local-test
``` ```
The output will looks like:
[comment]: <> (✂✂✂ auto generated help start ✂✂✂)
```
Usage: ./dev-cli.py [OPTIONS] COMMAND [ARGS]...
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────╮
│ check-code-style Check code style by calling darker + flake8 │
│ coverage Run and show coverage. │
│ diffsettings Run "diffsettings" manage command against a "local_test" YunoHost │
│ installation. │
│ fix-code-style Fix code style of all django_example_ynh source code files via │
│ darker │
│ install Run pip-sync and install 'django_example_ynh' via pip as editable. │
│ local-test Build a "local_test" YunoHost installation and start the Django dev. │
│ server against it. │
│ mypy Run Mypy (configured in pyproject.toml) │
│ publish Build and upload this project to PyPi │
│ safety Run safety check against current requirements files │
│ test Compile YunoHost files and run Django unittests │
│ tox Run tox │
│ update Update "requirements*.txt" dependencies files │
│ update-test-snapshot-files Update all test snapshot files (by remove and recreate all snapshot │
│ files) │
│ version Print version and exit │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
```
[comment]: <> (✂✂✂ auto generated help end ✂✂✂)
Notes: Notes:
* SQlite database will be used * SQlite database will be used

View file

@ -6,7 +6,7 @@ name = "Django Example"
description.en = "Application demonstrating the integration of a Django project under YunoHost" description.en = "Application demonstrating the integration of a Django project under YunoHost"
description.fr = "Application démontrant l'intégration d'un projet Django sous YunoHost" description.fr = "Application démontrant l'intégration d'un projet Django sous YunoHost"
version = "0.2.0~ynh2" version = "0.2.0~ynh3"
maintainers = ["Jens Diemer"] maintainers = ["Jens Diemer"]

View file

@ -25,14 +25,9 @@ dependencies = [
dev = [ dev = [
"bx_django_utils", # https://github.com/boxine/bx_django_utils "bx_django_utils", # https://github.com/boxine/bx_django_utils
"beautifulsoup4", # https://pypi.org/project/beautifulsoup4/ "beautifulsoup4", # https://pypi.org/project/beautifulsoup4/
#
# TODO: Remove "pytest" and use normal unittests ;)
"pytest",
"pytest-cov",
"pytest-django",
#
"manageprojects>=0.15.0", # https://github.com/jedie/manageprojects "manageprojects>=0.15.0", # https://github.com/jedie/manageprojects
"pip-tools", # https://github.com/jazzband/pip-tools/ "pip-tools", # https://github.com/jazzband/pip-tools/
"tblib", # https://github.com/ionelmc/python-tblib
"tox", # https://github.com/tox-dev/tox "tox", # https://github.com/tox-dev/tox
"coverage", # https://github.com/nedbat/coveragepy "coverage", # https://github.com/nedbat/coveragepy
"autopep8", # https://github.com/hhatto/autopep8 "autopep8", # https://github.com/hhatto/autopep8
@ -56,7 +51,6 @@ dev = [
# to avoid errors like: # to avoid errors like:
# In --require-hashes mode, all requirements must have their versions pinned with ==. These do not: ... # In --require-hashes mode, all requirements must have their versions pinned with ==. These do not: ...
"tomli", # Only needed for Python <3.11 "tomli", # Only needed for Python <3.11
"exceptiongroup", # needed by pytest
] ]
[project.urls] [project.urls]
@ -108,47 +102,18 @@ line_length=119
lines_after_imports=2 lines_after_imports=2
[tool.pytest.ini_options]
# https://docs.pytest.org/en/latest/customize.html#pyproject-toml
minversion = "6.0"
norecursedirs = ".* .git __pycache__ conf local_test coverage* dist htmlcov"
# sometimes helpfull "addopts" arguments:
# -vv
# --verbose
# --capture=no
# --trace-config
# --full-trace
# -p no:warnings
addopts = """
--reuse-db
--nomigrations
--cov=.
--cov-config=pyproject.toml
--cov-report term-missing
--cov-report html
--cov-report xml
--no-cov-on-fail
--showlocals
--doctest-modules
--failed-first
--new-first
"""
[tool.coverage.run] [tool.coverage.run]
branch = true branch = true
parallel = true parallel = true
concurrency = ["multiprocessing"] concurrency = ["multiprocessing"]
source = ['.'] source = ['.']
# TODO: pytest -> Django unitests: command_line = './dev-cli.py test'
#command_line = '-m unittest --verbose --locals --buffer'
command_line = '-m pytest'
disable_warnings = ["couldnt-parse"] disable_warnings = ["couldnt-parse"]
[tool.coverage.report] [tool.coverage.report]
omit = ['.*', '*/tests/*'] omit = ['.*', '*/tests/*']
skip_empty = true skip_empty = true
fail_under = 30 fail_under = 10
show_missing = true show_missing = true
exclude_lines = [ exclude_lines = [
'if self.debug:', 'if self.debug:',

View file

@ -1,5 +1,5 @@
# #
# This file is autogenerated by pip-compile with Python 3.11 # This file is autogenerated by pip-compile with Python 3.10
# by the following command: # by the following command:
# #
# ./dev-cli.py update # ./dev-cli.py update
@ -19,7 +19,9 @@ astor==0.8.1 \
async-timeout==4.0.3 \ async-timeout==4.0.3 \
--hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \
--hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028
# via django-example-ynh (pyproject.toml) # via
# django-example-ynh (pyproject.toml)
# redis
autoflake==2.2.1 \ autoflake==2.2.1 \
--hash=sha256:265cde0a43c1f44ecfb4f30d95b0437796759d07be7706a2f70e4719234c0f79 \ --hash=sha256:265cde0a43c1f44ecfb4f30d95b0437796759d07be7706a2f70e4719234c0f79 \
--hash=sha256:62b7b6449a692c3c9b0c916919bbc21648da7281e8506bcf8d3f8280e431ebc1 --hash=sha256:62b7b6449a692c3c9b0c916919bbc21648da7281e8506bcf8d3f8280e431ebc1
@ -66,9 +68,9 @@ build==1.0.3 \
--hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \ --hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \
--hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f --hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f
# via pip-tools # via pip-tools
bx-django-utils==67 \ bx-django-utils==69 \
--hash=sha256:8740fdaf98ed68a8ddb3af025d9b4f87c99101405898ddca86810b0c384b215a \ --hash=sha256:39e96b8ad47bcf36d6713e4e42c8d09deb21e413160dc2944f17b7d2e2244713 \
--hash=sha256:aca0ae5c91a62e4f594172b8c43468c701516f99ae50d99412d5299ba375df03 --hash=sha256:59b806aa36b50184f14bd0f7a61fb66c478fa231a44f92472360ce0cf1616013
# via # via
# django-example # django-example
# django-example-ynh (pyproject.toml) # django-example-ynh (pyproject.toml)
@ -83,9 +85,9 @@ cachetools==5.3.2 \
--hash=sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2 \ --hash=sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2 \
--hash=sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1 --hash=sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1
# via tox # via tox
certifi==2023.7.22 \ certifi==2023.11.17 \
--hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ --hash=sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1 \
--hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 --hash=sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474
# via requests # via requests
cffi==1.16.0 \ cffi==1.16.0 \
--hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \
@ -270,11 +272,11 @@ colorlog==6.7.0 \
--hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \
--hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5
# via django-yunohost-integration # via django-yunohost-integration
cookiecutter==2.4.0 \ cookiecutter==2.5.0 \
--hash=sha256:6d1494e66a784f23324df9d593f3e43af3db4f4b926b9e49e6ff060169fc042a \ --hash=sha256:8aa2f12ed11bc05628651e9dc4353a10571dd9908aaaaeec959a2b9ea465a5d2 \
--hash=sha256:8344663028abc08ec09b912e663636a97e1775bffe973425ec0107431acd390e --hash=sha256:e61e9034748e3f41b8bd2c11f00d030784b48711c4d5c42363c50989a65331ec
# via manageprojects # via manageprojects
coverage[toml]==7.3.2 \ coverage==7.3.2 \
--hash=sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1 \ --hash=sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1 \
--hash=sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63 \ --hash=sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63 \
--hash=sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9 \ --hash=sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9 \
@ -327,9 +329,7 @@ coverage[toml]==7.3.2 \
--hash=sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738 \ --hash=sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738 \
--hash=sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a \ --hash=sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a \
--hash=sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4 --hash=sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4
# via # via django-example-ynh (pyproject.toml)
# django-example-ynh (pyproject.toml)
# pytest-cov
cryptography==41.0.5 \ cryptography==41.0.5 \
--hash=sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf \ --hash=sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf \
--hash=sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84 \ --hash=sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84 \
@ -410,9 +410,9 @@ editorconfig==0.12.3 \
# via # via
# django-example-ynh (pyproject.toml) # django-example-ynh (pyproject.toml)
# manageprojects # manageprojects
exceptiongroup==1.1.3 \ exceptiongroup==1.2.0 \
--hash=sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9 \ --hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
--hash=sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3 --hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
# via django-example-ynh (pyproject.toml) # via django-example-ynh (pyproject.toml)
filelock==3.13.1 \ filelock==3.13.1 \
--hash=sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e \ --hash=sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e \
@ -438,9 +438,9 @@ icdiff==2.0.7 \
--hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \ --hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \
--hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f --hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f
# via django-tools # via django-tools
idna==3.4 \ idna==3.6 \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
# via requests # via requests
importlib-metadata==6.8.0 \ importlib-metadata==6.8.0 \
--hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \
@ -448,10 +448,6 @@ importlib-metadata==6.8.0 \
# via # via
# keyring # keyring
# twine # twine
iniconfig==2.0.0 \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
# via pytest
isort==5.12.0 \ isort==5.12.0 \
--hash=sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504 \ --hash=sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504 \
--hash=sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6 --hash=sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6
@ -470,9 +466,9 @@ jinja2==3.1.2 \
--hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
--hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
# via cookiecutter # via cookiecutter
keyring==24.2.0 \ keyring==24.3.0 \
--hash=sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6 \ --hash=sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836 \
--hash=sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509 --hash=sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25
# via twine # via twine
manageprojects==0.15.3 \ manageprojects==0.15.3 \
--hash=sha256:052fe4e6ce8d2e36f9ec9adaffce918874512a96e3b92bc53a5cb3bfbf3ad3ad \ --hash=sha256:052fe4e6ce8d2e36f9ec9adaffce918874512a96e3b92bc53a5cb3bfbf3ad3ad \
@ -556,34 +552,34 @@ more-itertools==10.1.0 \
--hash=sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a \ --hash=sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a \
--hash=sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6 --hash=sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6
# via jaraco-classes # via jaraco-classes
mypy==1.6.1 \ mypy==1.7.1 \
--hash=sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7 \ --hash=sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340 \
--hash=sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e \ --hash=sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49 \
--hash=sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c \ --hash=sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82 \
--hash=sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169 \ --hash=sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce \
--hash=sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208 \ --hash=sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb \
--hash=sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0 \ --hash=sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51 \
--hash=sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1 \ --hash=sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5 \
--hash=sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1 \ --hash=sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e \
--hash=sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7 \ --hash=sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7 \
--hash=sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45 \ --hash=sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33 \
--hash=sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143 \ --hash=sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9 \
--hash=sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5 \ --hash=sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1 \
--hash=sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f \ --hash=sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6 \
--hash=sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd \ --hash=sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a \
--hash=sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245 \ --hash=sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe \
--hash=sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f \ --hash=sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7 \
--hash=sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332 \ --hash=sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200 \
--hash=sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30 \ --hash=sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7 \
--hash=sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183 \ --hash=sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a \
--hash=sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f \ --hash=sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28 \
--hash=sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85 \ --hash=sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea \
--hash=sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46 \ --hash=sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120 \
--hash=sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71 \ --hash=sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d \
--hash=sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660 \ --hash=sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42 \
--hash=sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb \ --hash=sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea \
--hash=sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c \ --hash=sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2 \
--hash=sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a --hash=sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a
# via # via
# django-example-ynh (pyproject.toml) # django-example-ynh (pyproject.toml)
# manageprojects # manageprojects
@ -621,7 +617,6 @@ packaging==23.2 \
# dparse # dparse
# gunicorn # gunicorn
# pyproject-api # pyproject-api
# pytest
# safety # safety
# tox # tox
pathspec==0.11.2 \ pathspec==0.11.2 \
@ -636,9 +631,9 @@ pkginfo==1.9.6 \
--hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \ --hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \
--hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046 --hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046
# via twine # via twine
platformdirs==3.11.0 \ platformdirs==4.0.0 \
--hash=sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3 \ --hash=sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b \
--hash=sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e --hash=sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731
# via # via
# black # black
# tox # tox
@ -646,9 +641,7 @@ platformdirs==3.11.0 \
pluggy==1.3.0 \ pluggy==1.3.0 \
--hash=sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12 \ --hash=sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12 \
--hash=sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7 --hash=sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7
# via # via tox
# pytest
# tox
pprintpp==0.4.0 \ pprintpp==0.4.0 \
--hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \ --hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \
--hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403 --hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403
@ -686,9 +679,9 @@ pyflakes==3.1.0 \
# django-example-ynh (pyproject.toml) # django-example-ynh (pyproject.toml)
# flake8 # flake8
# manageprojects # manageprojects
pygments==2.16.1 \ pygments==2.17.2 \
--hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \ --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \
--hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29 --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367
# via # via
# darker # darker
# readme-renderer # readme-renderer
@ -701,21 +694,6 @@ pyproject-hooks==1.0.0 \
--hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \ --hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \
--hash=sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5 --hash=sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5
# via build # via build
pytest==7.4.3 \
--hash=sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac \
--hash=sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5
# via
# django-example-ynh (pyproject.toml)
# pytest-cov
# pytest-django
pytest-cov==4.1.0 \
--hash=sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6 \
--hash=sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a
# via django-example-ynh (pyproject.toml)
pytest-django==4.7.0 \
--hash=sha256:4e1c79d5261ade2dd58d91208017cd8f62cb4710b56e012ecd361d15d5d662a2 \
--hash=sha256:92d6fd46b1d79b54fb6b060bbb39428073396cec717d5f2e122a990d4b6aa5e8
# via django-example-ynh (pyproject.toml)
python-dateutil==2.8.2 \ python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
@ -812,9 +790,9 @@ rfc3986==2.0.0 \
--hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \
--hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c
# via twine # via twine
rich==13.6.0 \ rich==13.7.0 \
--hash=sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245 \ --hash=sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa \
--hash=sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef --hash=sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235
# via # via
# cli-base-utilities # cli-base-utilities
# cookiecutter # cookiecutter
@ -905,6 +883,10 @@ sqlparse==0.4.4 \
--hash=sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3 \ --hash=sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3 \
--hash=sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c --hash=sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c
# via django # via django
tblib==3.0.0 \
--hash=sha256:80a6c77e59b55e83911e1e607c649836a69c103963c5f28a46cbeef44acf8129 \
--hash=sha256:93622790a0a29e04f0346458face1e144dc4d32f493714c6c3dff82a4adb77e6
# via django-example-ynh (pyproject.toml)
text-unidecode==1.3 \ text-unidecode==1.3 \
--hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \ --hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \
--hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 --hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93
@ -921,11 +903,21 @@ tomli==2.0.1 \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
# via # via
# autoflake
# autopep8
# black
# build
# django-example-ynh (pyproject.toml) # django-example-ynh (pyproject.toml)
# dparse
# flynt # flynt
tomlkit==0.12.2 \ # mypy
--hash=sha256:df32fab589a81f0d7dc525a4267b6d7a64ee99619cbd1eeb0fae32c1dd426977 \ # pip-tools
--hash=sha256:eeea7ac7563faeab0a1ed8fe12c2e5a51c61f933f2502f7e9db0241a65163ad0 # pyproject-api
# pyproject-hooks
# tox
tomlkit==0.12.3 \
--hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \
--hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba
# via # via
# cli-base-utilities # cli-base-utilities
# manageprojects # manageprojects
@ -945,17 +937,19 @@ typing-extensions==4.8.0 \
--hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \
--hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef
# via # via
# asgiref
# black
# mypy # mypy
# rich-click # rich-click
urllib3==2.0.7 \ urllib3==2.1.0 \
--hash=sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84 \ --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \
--hash=sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54
# via # via
# requests # requests
# twine # twine
virtualenv==20.24.6 \ virtualenv==20.24.7 \
--hash=sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af \ --hash=sha256:69050ffb42419c91f6c1284a7b24e0475d793447e35929b488bf6a0aade39353 \
--hash=sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381 --hash=sha256:a18b3fd0314ca59a2e9f4b556819ed07183b3e9a3702ecfe213f593d44f7b3fd
# via tox # via tox
webencodings==0.5.1 \ webencodings==0.5.1 \
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
@ -975,9 +969,9 @@ pip==23.3.1 \
--hash=sha256:1fcaa041308d01f14575f6d0d2ea4b75a3e2871fe4f9c694976f908768e14174 \ --hash=sha256:1fcaa041308d01f14575f6d0d2ea4b75a3e2871fe4f9c694976f908768e14174 \
--hash=sha256:55eb67bb6171d37447e82213be585b75fe2b12b359e993773aca4de9247a052b --hash=sha256:55eb67bb6171d37447e82213be585b75fe2b12b359e993773aca4de9247a052b
# via pip-tools # via pip-tools
setuptools==68.2.2 \ setuptools==69.0.2 \
--hash=sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87 \ --hash=sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2 \
--hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a --hash=sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6
# via # via
# django-axes # django-axes
# pip-tools # pip-tools

View file

View file

@ -1,43 +0,0 @@
"""
Special pytest init:
- Build a "local_test" YunoHost installation
- init Django with this local test installation
So the pytests will run against this local test installation
"""
import os
import sys
from pathlib import Path
import django
from django_yunohost_integration.local_test import CreateResults, create_local_test
BASE_PATH = Path(__file__).parent.parent
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
def pytest_configure():
print('Compile YunoHost files...')
result: CreateResults = create_local_test(
django_settings_path=BASE_PATH / 'conf' / 'settings.py',
destination=BASE_PATH / 'local_test',
runserver=False,
extra_replacements={
'__DEBUG_ENABLED__': '0', # "1" or "0" string
'__LOG_LEVEL__': 'INFO',
'__ADMIN_EMAIL__': 'foo-bar@test.tld',
'__DEFAULT_FROM_EMAIL__': 'django_app@test.tld',
},
)
print('Local test files created:')
print(result)
os.chdir(result.data_dir_path)
data_dir = str(result.data_dir_path)
if data_dir not in sys.path:
sys.path.insert(0, data_dir)
django.setup()

View file

@ -1,158 +0,0 @@
<div id="container">
<!-- Header -->
<div id="header">
<div id="branding">
<h1 id="site-name">
<a href="/">
Debug View
</a>
</h1>
</div>
</div>
<!-- END Header -->
<nav aria-label="Breadcrumbs">
<div class="breadcrumbs">
<a href="/app_path/admin/">
Home
</a>
</div>
</nav>
<div class="main" id="main">
<div class="content" id="content-start" tabindex="-1">
<!-- Content -->
<div class="colM" id="content">
<h2>
YunoHost Django Example Project v0.2.0
</h2>
<ul>
<li>
<a href="/app_path/admin/">
Django Admin
</a>
</li>
<li>
<a href="/app_path/login-required/">
Test Login Required View
</a>
</li>
</ul>
<p>
Log in to see more information
</p>
<table>
<tr>
<td>
<code>
settings.SETTINGS_MODULE
</code>
:
</td>
<td>
<code>
settings
</code>
</td>
</tr>
<tr>
<td>
Env. type:
</td>
<td>
<code>
None
</code>
</td>
</tr>
<tr>
<td>
User:
</td>
<td>
AnonymousUser
</td>
</tr>
<tr>
<td>
Remote Address:
</td>
<td>
127.0.0.1
</td>
</tr>
<tr>
<td>
Process User:
</td>
<td>
(ID: :)
</td>
</tr>
<tr>
<td>
Executable:
</td>
<td>
</td>
</tr>
<tr>
<td>
Process ID:
</td>
<td>
</td>
</tr>
<tr>
<td>
Python Version:
</td>
<td>
</td>
</tr>
<tr>
<td>
Sys prefix:
</td>
<td>
</td>
</tr>
<tr>
<td>
Current work dir:
</td>
<td>
</td>
</tr>
<tr>
<td>
OS uname:
</td>
<td>
</td>
</tr>
<tr>
<td>
OS Environment:
</td>
<td>
</td>
</tr>
<tr>
<td>
META:
</td>
<td>
</td>
</tr>
</table>
<br class="clear"/>
</div>
<!-- END Content -->
<hr/>
<p>
<a href="https://github.com/jedie/django_example">
github.com/jedie/django_example
</a>
</p>
</div>
</div>
</div>

View file

@ -1,106 +0,0 @@
import os
from pathlib import Path
from unittest import TestCase
try:
import tomllib # New in Python 3.11
except ImportError:
import tomli as tomllib
from bx_django_utils.filename import clean_filename
from bx_py_utils.path import assert_is_dir, assert_is_file
from django_tools.unittest_utils.project_setup import check_editor_config
from django_yunohost_integration.test_utils import assert_project_version
from django_example_ynh import __version__
PACKAGE_ROOT = Path(__file__).parent.parent
def assert_file_contains_string(file_path, string):
with file_path.open('r') as f:
for line in f:
if string in line:
return
raise AssertionError(f'File {file_path} does not contain {string!r} !')
def test_version():
assert '+ynh' in __version__, f'{__version__!r} does not contain "+ynh"'
# pyproject.toml needs a PEP 440 conform version and used "+ynh"
# the YunoHost syntax is: "~ynh", just "convert this:
manifest_version = __version__.replace('+', '~')
assert_file_contains_string(
file_path=Path(PACKAGE_ROOT, 'manifest.toml'),
string=f'version = "{manifest_version}"',
)
if 'GITHUB_ACTION' not in os.environ:
# Github has a rate-limiting... So don't fetch the API if we run as GitHub action
assert_project_version(
current_version=__version__,
github_project_url='https://github.com/jedie/django-example',
)
def test_screenshot_filenames():
"""
https://forum.yunohost.org/t/yunohost-bot-cant-handle-spaces-in-screenshots/19483
"""
screenshot_path = PACKAGE_ROOT / 'doc' / 'screenshots'
assert_is_dir(screenshot_path)
renamed = []
for file_path in screenshot_path.iterdir():
file_name = file_path.name
if file_name.startswith('.'):
continue
cleaned_name = clean_filename(file_name)
if cleaned_name != file_name:
new_path = file_path.with_name(cleaned_name)
file_path.rename(new_path)
renamed.append(f'{file_name!r} renamed to {cleaned_name!r}')
assert not renamed, f'Bad screenshots file names found: {", ".join(renamed)}'
def test_check_editor_config():
check_editor_config(package_root=PACKAGE_ROOT)
class ManifestTestCase(TestCase):
def test_manifest_toml(self):
manifest_path = PACKAGE_ROOT / 'manifest.toml'
assert_is_file(manifest_path)
cfg = tomllib.loads(manifest_path.read_text(encoding='UTF-8'))
self.assertEqual(cfg['packaging_format'], 2)
self.assertEqual(
set(cfg['install'].keys()),
{
'admin',
'admin_email',
'debug_enabled',
'default_from_email',
'domain',
'init_main_permission',
'log_level',
'path',
},
)
self.assertEqual(
set(cfg['resources'].keys()),
{
'apt',
'data_dir',
'database',
'install_dir',
'permissions',
'ports',
'system_user',
},
)

View file

@ -1,8 +0,0 @@
from unittest.case import TestCase
from django_yunohost_integration.test_utils import generate_basic_auth
class TestUtilsTestCase(TestCase):
def test_generate_basic_auth(self):
assert generate_basic_auth(username='test', password='test123') == 'basic dGVzdDp0ZXN0MTIz'