mirror of
https://github.com/YunoHost-Apps/django-fritzconnection_ynh.git
synced 2024-09-03 18:26:24 +02:00
Apply manageprojects updates
This commit is contained in:
parent
869c14c61a
commit
4a4e876d0f
50 changed files with 3453 additions and 2290 deletions
|
@ -1,4 +1,4 @@
|
||||||
# see http://editorconfig.org
|
# see https://editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
|
@ -10,11 +10,11 @@ trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[*.py]
|
[*.py]
|
||||||
max_line_length = 100
|
max_line_length = 119
|
||||||
|
|
||||||
[{Makefile,**.mk}]
|
[{Makefile,**.mk}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
insert_final_newline = false
|
insert_final_newline = false
|
||||||
|
|
||||||
[*.yml]
|
[{*.yaml,*.yml}]
|
||||||
indent_style = tab
|
indent_size = 2
|
||||||
|
|
4
.flake8
4
.flake8
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# Move to pyproject.toml after: https://gitlab.com/pycqa/flake8/-/issues/428
|
# Move to pyproject.toml after: https://github.com/PyCQA/flake8/issues/234
|
||||||
#
|
#
|
||||||
[flake8]
|
[flake8]
|
||||||
exclude = .pytest_cache, .tox, dist, htmlcov, local_test
|
exclude = .*, dist, htmlcov, local_test
|
||||||
ignore = F405
|
ignore = F405
|
||||||
max-line-length = 119
|
max-line-length = 119
|
||||||
|
|
17
.github/workflows/package_linter.yml
vendored
17
.github/workflows/package_linter.yml
vendored
|
@ -1,6 +1,8 @@
|
||||||
name: YunoHost apps package linter
|
name: YunoHost apps package linter
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
# Allow to manually trigger the workflow
|
||||||
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
@ -12,12 +14,25 @@ jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install toml
|
||||||
|
|
||||||
- name: 'Clone YunoHost apps package linter'
|
- name: 'Clone YunoHost apps package linter'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 https://github.com/YunoHost/package_linter ~/package_linter
|
git clone --depth=1 https://github.com/YunoHost/package_linter ~/package_linter
|
||||||
|
|
||||||
|
- name: 'Install requirements'
|
||||||
|
run: pip3 install toml
|
||||||
|
|
||||||
- name: 'Run linter'
|
- name: 'Run linter'
|
||||||
run: |
|
run: |
|
||||||
~/package_linter/package_linter.py .
|
~/package_linter/package_linter.py .
|
||||||
|
|
56
.github/workflows/pytest.yml
vendored
56
.github/workflows/pytest.yml
vendored
|
@ -1,56 +0,0 @@
|
||||||
name: pytest
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 8 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
max-parallel: 2
|
|
||||||
matrix:
|
|
||||||
python-version: ["3.10", "3.9", "3.8", "3.7"]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: 'fetch master'
|
|
||||||
run: |
|
|
||||||
git fetch origin master
|
|
||||||
- name: 'Set up Python ${{ matrix.python-version }}'
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: '${{ matrix.python-version }}'
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.cache/
|
|
||||||
key: dot-cache-files
|
|
||||||
|
|
||||||
- name: 'Install package'
|
|
||||||
run: |
|
|
||||||
pip3 install poetry
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: 'List installed packages'
|
|
||||||
run: |
|
|
||||||
poetry run pip freeze
|
|
||||||
|
|
||||||
- name: 'Run tests with Python v${{ matrix.python-version }}'
|
|
||||||
run: |
|
|
||||||
make pytest
|
|
||||||
|
|
||||||
- name: 'Run Safety check'
|
|
||||||
run: |
|
|
||||||
make safety
|
|
||||||
|
|
||||||
- name: 'Upload coverage report'
|
|
||||||
uses: codecov/codecov-action@v2
|
|
||||||
with:
|
|
||||||
fail_ci_if_error: false
|
|
||||||
verbose: true
|
|
66
.github/workflows/tests.yml
vendored
Normal file
66
.github/workflows/tests.yml
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
|
||||||
|
|
||||||
|
name: tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 8 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
python-version: ['3.12', '3.11']
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
echo $GITHUB_REF $GITHUB_SHA
|
||||||
|
git clone https://github.com/$GITHUB_REPOSITORY.git .
|
||||||
|
git fetch origin $GITHUB_SHA:temporary-ci-branch
|
||||||
|
git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)
|
||||||
|
- name: 'fetch master'
|
||||||
|
run: |
|
||||||
|
git fetch origin master
|
||||||
|
|
||||||
|
- name: 'Set up Python ${{ matrix.python-version }}'
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
# https://github.com/marketplace/actions/setup-python
|
||||||
|
with:
|
||||||
|
python-version: '${{ matrix.python-version }}'
|
||||||
|
cache: 'pip' # caching pip dependencies
|
||||||
|
cache-dependency-path: '**/requirements.*.txt'
|
||||||
|
|
||||||
|
- name: 'Bootstrap dev venv'
|
||||||
|
# The first CLI call will create the .venv
|
||||||
|
run: |
|
||||||
|
./dev-cli.py version
|
||||||
|
|
||||||
|
- name: 'dev CLI help'
|
||||||
|
run: |
|
||||||
|
./dev-cli.py --help
|
||||||
|
|
||||||
|
- name: 'Run pip-audit'
|
||||||
|
run: |
|
||||||
|
./dev-cli.py pip-audit
|
||||||
|
|
||||||
|
- name: 'Run tests with Python v${{ matrix.python-version }}'
|
||||||
|
env:
|
||||||
|
PYTHONUNBUFFERED: 1
|
||||||
|
PYTHONWARNINGS: always
|
||||||
|
run: |
|
||||||
|
.venv/bin/coverage erase
|
||||||
|
./dev-cli.py coverage
|
||||||
|
|
||||||
|
- name: 'Upload coverage report'
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
# https://github.com/marketplace/actions/codecov
|
||||||
|
with:
|
||||||
|
fail_ci_if_error: false
|
||||||
|
verbose: true
|
||||||
|
|
13
.gitignore
vendored
13
.gitignore
vendored
|
@ -1,11 +1,18 @@
|
||||||
.*
|
.*
|
||||||
|
*.egg-info
|
||||||
|
__pycache__
|
||||||
|
/dist/
|
||||||
|
/build/
|
||||||
|
/coverage.*
|
||||||
|
/htmlcov/
|
||||||
|
*.orig
|
||||||
|
|
||||||
!.github
|
!.github
|
||||||
!.editorconfig
|
!.editorconfig
|
||||||
!.flake8
|
!.flake8
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
!/doc/screenshots/.gitkeep
|
!/doc/screenshots/.gitkeep
|
||||||
__pycache__
|
|
||||||
secret.txt
|
secret.txt
|
||||||
/local_test/
|
/local_test/
|
||||||
/coverage.xml
|
|
||||||
/htmlcov/
|
|
||||||
|
|
8
LICENSE
8
LICENSE
|
@ -1,7 +1,7 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
The GNU General Public License does not permit incorporating your program
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
58
Makefile
58
Makefile
|
@ -1,58 +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-poetry: ## install or update poetry
|
|
||||||
curl -sSL https://install.python-poetry.org | python3 -
|
|
||||||
|
|
||||||
install: check-poetry ## install project via poetry
|
|
||||||
poetry install
|
|
||||||
|
|
||||||
update: check-poetry ## update the sources and installation and generate "conf/requirements.txt"
|
|
||||||
poetry self update
|
|
||||||
poetry update -v
|
|
||||||
poetry export -f requirements.txt --output conf/requirements.txt
|
|
||||||
|
|
||||||
lint: ## Run code formatters and linter
|
|
||||||
poetry run isort --check-only .
|
|
||||||
poetry run flake8 .
|
|
||||||
|
|
||||||
fix-code-style: ## Fix code formatting
|
|
||||||
poetry run black --verbose --safe --line-length=${MAX_LINE_LENGTH} --skip-string-normalization .
|
|
||||||
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
|
|
33
check_process
Normal file
33
check_process
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# See here for more information
|
||||||
|
# https://github.com/YunoHost/package_check#syntax-check_process-file
|
||||||
|
|
||||||
|
# Move this file from check_process.default to check_process when you have filled it.
|
||||||
|
|
||||||
|
;; Test complet
|
||||||
|
; Manifest
|
||||||
|
domain="domain.tld" (DOMAIN)
|
||||||
|
path="/path" (PATH)
|
||||||
|
admin="john" (USER)
|
||||||
|
is_public=1 (PUBLIC|public=1|private=0)
|
||||||
|
password="pass"
|
||||||
|
port="666" (PORT)
|
||||||
|
; Checks
|
||||||
|
pkg_linter=1
|
||||||
|
setup_sub_dir=1
|
||||||
|
setup_root=1
|
||||||
|
setup_nourl=0
|
||||||
|
setup_private=0
|
||||||
|
setup_public=1
|
||||||
|
upgrade=1
|
||||||
|
backup_restore=1
|
||||||
|
multi_instance=1
|
||||||
|
port_already_use=0
|
||||||
|
change_url=1
|
||||||
|
;;; Options
|
||||||
|
Email=
|
||||||
|
Notification=none
|
||||||
|
;;; Upgrade options
|
||||||
|
; commit=CommitHash
|
||||||
|
name=Name and date of the commit.
|
||||||
|
manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666&
|
||||||
|
|
|
@ -13,8 +13,8 @@ workers = multiprocessing.cpu_count() * 2 + 1
|
||||||
loglevel = 'info'
|
loglevel = 'info'
|
||||||
|
|
||||||
# https://docs.gunicorn.org/en/latest/settings.html#logging
|
# https://docs.gunicorn.org/en/latest/settings.html#logging
|
||||||
accesslog = '/var/log/__APP__/__APP__.log'
|
accesslog = '__LOG_FILE__'
|
||||||
errorlog = '/var/log/__APP__/__APP__.log'
|
errorlog = '__LOG_FILE__'
|
||||||
|
|
||||||
# https://docs.gunicorn.org/en/latest/settings.html#pidfile
|
# https://docs.gunicorn.org/en/latest/settings.html#pidfile
|
||||||
pidfile = '__INSTALL_DIR__/app/gunicorn.pid'
|
pidfile = '__DATA_DIR__/gunicorn.pid' # /home/yunohost.app/$app/gunicorn.pid
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!__INSTALL_DIR__/venv/bin/python
|
#!__DATA_DIR__/venv/bin/python
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
location __PATH__/static/ {
|
location __PATH__/static/ {
|
||||||
# Service static files by nginx
|
# Service static files by nginx
|
||||||
# e.g.: /var/www/$app/static
|
# e.g.: /var/www/$app/static/
|
||||||
alias __INSTALL_DIR__/public/static/;
|
alias __INSTALL_DIR__/static/;
|
||||||
expires 30d;
|
expires 30d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,201 +1,425 @@
|
||||||
asgiref==3.5.2 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
#
|
||||||
--hash=sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4 \
|
# This file is autogenerated by pip-compile with Python 3.12
|
||||||
--hash=sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424
|
# by the following command:
|
||||||
async-timeout==4.0.2 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
#
|
||||||
--hash=sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15 \
|
# ./dev-cli.py update
|
||||||
--hash=sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c
|
#
|
||||||
bleach==5.0.1 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
asgiref==3.8.1 \
|
||||||
--hash=sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a \
|
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \
|
||||||
--hash=sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c
|
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590
|
||||||
bx-django-utils==35 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# via
|
||||||
--hash=sha256:341b27ad0b72a903acf2f28def0fe371def811c1b2305da9806124869a698fc8 \
|
# django
|
||||||
--hash=sha256:5151806d349a9dafc8dba9636239422022bab211b5b02afa52fce1f58ec2e6ab
|
# django-axes
|
||||||
bx-py-utils==69 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
async-timeout==4.0.3 \
|
||||||
--hash=sha256:728fd575c4d5048e114b502a97d19679f9abcda90889a6896534c48348320460 \
|
--hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \
|
||||||
--hash=sha256:b25419e020c9c5ea16938a45cf5120086a5ac29648be78a8eb98ae202515fee1
|
--hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028
|
||||||
certifi==2022.9.24 ; python_version >= "3.7" and python_version < "4" \
|
# via cli-base-utilities
|
||||||
--hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \
|
bleach==6.1.0 \
|
||||||
--hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382
|
--hash=sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe \
|
||||||
charset-normalizer==2.1.1 ; python_version >= "3.7" and python_version < "4" \
|
--hash=sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6
|
||||||
--hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \
|
# via django-tools
|
||||||
--hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f
|
bx-django-utils==79 \
|
||||||
colorama==0.4.5 ; python_version >= "3.7" and python_full_version < "4.0.0" and sys_platform == "win32" \
|
--hash=sha256:cb66087d4e9396281acf5a4394b749cff3062b66082d5726f6a8a342fdd35d0e \
|
||||||
--hash=sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da \
|
--hash=sha256:d50b10ace24b0b363574542faecf04a81029e2fec6d6e6525fe063ed06238e04
|
||||||
--hash=sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4
|
# via
|
||||||
colorlog==6.7.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# django-fritzconnection
|
||||||
--hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \
|
# django-tools
|
||||||
--hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5
|
bx-py-utils==98 \
|
||||||
deprecated==1.2.13 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:30fb49b0f0b21c9fbd544895480a1aa9da63f410572e4b46afbca792e64cec98 \
|
||||||
--hash=sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d \
|
--hash=sha256:ac8b193ff117420b77b43c043e50b195d6aa9ee7e72e22265ca699730b61f71f
|
||||||
--hash=sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d
|
# via
|
||||||
diff-match-patch==20200713 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# bx-django-utils
|
||||||
--hash=sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34 \
|
# cli-base-utilities
|
||||||
--hash=sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18
|
# django-fritzconnection
|
||||||
django-admin-sortable2==1.0.4 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# django-tools
|
||||||
--hash=sha256:e22956889533b48a35a7f02859ae3a939753fa9a7d7d532cefc2835b41bdcebb \
|
certifi==2024.7.4 \
|
||||||
--hash=sha256:f96044003176c6684c5f969792ca833a505d654fa0f7b24232a0a610e4332a53
|
--hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
|
||||||
django-axes==5.39.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
|
||||||
--hash=sha256:8f039f8e98f050f13f654efca599d8a04d0b57d330c590cf89ec2bf731c9a7fb \
|
# via requests
|
||||||
--hash=sha256:97702552f7939c81db5bba2ef855ae43f20df92fa261cb79fd4c8633ba3b3955
|
charset-normalizer==3.3.2 \
|
||||||
django-debug-toolbar==3.7.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
|
||||||
--hash=sha256:1e3acad24e3d351ba45c6fa2072e4164820307332a776b16c9f06d1f89503465 \
|
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
|
||||||
--hash=sha256:80de23066b624d3970fd296cf02d61988e5d56c31aa0dc4a428970b46e2883a8
|
--hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
|
||||||
django-fritzconnection==0.2.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
|
||||||
--hash=sha256:4dbc96661da17cfa0f57ee6e6cc0956574d47479aa688eedf136475bf96f870e \
|
--hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
|
||||||
--hash=sha256:5573ef7497fbd339e54c6067d9d7e223d820785d581cd5e6593af46c828a6425
|
--hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
|
||||||
django-ipware==4.0.2 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
|
||||||
--hash=sha256:602a58325a4808bd19197fef2676a0b2da2df40d0ecf21be414b2ff48c72ad05 \
|
--hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
|
||||||
--hash=sha256:878dbb06a87e25550798e9ef3204ed70a200dd8b15e47dcef848cf08244f04c9
|
--hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
|
||||||
django-redis==5.2.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
|
||||||
--hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \
|
--hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
|
||||||
--hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de
|
--hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
|
||||||
django-reversion-compare==0.15.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
|
||||||
--hash=sha256:d6f37b106aec287ae17a076bb7db1184ab02ab1898f0e8693f2779fbdaf71697 \
|
--hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
|
||||||
--hash=sha256:ed0264a2852d9d867023f1874948b8234dad9c2d2fa22ea18cfd5f28f304d7a0
|
--hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
|
||||||
django-reversion==5.0.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
|
||||||
--hash=sha256:acb600f8482147312a27bd58e63766aa0383310181e485e6eaa2f42d26502c9b \
|
--hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
|
||||||
--hash=sha256:c5955e09c4f290a8a3c5048b3f77d5ba75eae325c0fb1e571b0cd98df6a0017b
|
--hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
|
||||||
django-tagulous==1.3.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
|
||||||
--hash=sha256:ad3bb85f4cce83a47e4c0257143229cb92a294defa02fe661823b0442b35d478 \
|
--hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
|
||||||
--hash=sha256:d445590ae1b5cb9b8c5a425f97bf5f01148a33419c19edeb721ebd9fdd6792fe
|
--hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
|
||||||
django-tools==0.54.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
|
||||||
--hash=sha256:5040a91282be9d1c9d379b0c65da50bcb3691bff03cee54fd4123ace238c3a43 \
|
--hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
|
||||||
--hash=sha256:a7b7bfa5b9c5a81966454d17dffb2403cee25a806c858ee0486a08798227598f
|
--hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
|
||||||
django-yunohost-integration[ynh]==0.4.1 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
|
||||||
--hash=sha256:3769859db283a6b4d17468aeb1decab2f79d4b3e128b341342948e7bb3121e8a \
|
--hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
|
||||||
--hash=sha256:e097cd209f3e09cbe325eadea36e3eb64c051690297c38dd89a1cd64bc35d92e
|
--hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
|
||||||
django==3.2.16 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
|
||||||
--hash=sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121 \
|
--hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
|
||||||
--hash=sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d
|
--hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
|
||||||
fritzconnection==1.10.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
|
||||||
--hash=sha256:0b52772ff4e844edc510371ec6b9b0d2b56846c887fcbc7031e63d2d1f1e4bc0
|
--hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
|
||||||
gunicorn==20.1.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
|
||||||
--hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \
|
--hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
|
||||||
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
|
--hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
|
||||||
icdiff==2.0.5 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
|
||||||
--hash=sha256:35d24b728e48b7e0a12bdb69386d3bfc7eef4fe922d0ac1cd70d6e5c11630bae
|
--hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
|
||||||
idna==3.4 ; python_version >= "3.7" and python_version < "4" \
|
--hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
|
||||||
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
|
--hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
|
||||||
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
|
--hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
|
||||||
importlib-metadata==4.2.0 ; python_version >= "3.7" and python_version < "3.8" \
|
--hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
|
||||||
--hash=sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b \
|
--hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
|
||||||
--hash=sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31
|
--hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
|
||||||
packaging==21.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
|
||||||
--hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \
|
--hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
|
||||||
--hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
|
--hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
|
||||||
pprintpp==0.4.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
|
||||||
|
--hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
|
||||||
|
--hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
|
||||||
|
--hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
|
||||||
|
--hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
|
||||||
|
--hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
|
||||||
|
--hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
|
||||||
|
--hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
|
||||||
|
--hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
|
||||||
|
--hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
|
||||||
|
--hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
|
||||||
|
--hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
|
||||||
|
--hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
|
||||||
|
--hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
|
||||||
|
--hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
|
||||||
|
--hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
|
||||||
|
--hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
|
||||||
|
--hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
|
||||||
|
--hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
|
||||||
|
--hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
|
||||||
|
--hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
|
||||||
|
--hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
|
||||||
|
--hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
|
||||||
|
--hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
|
||||||
|
--hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
|
||||||
|
--hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
|
||||||
|
--hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
|
||||||
|
--hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
|
||||||
|
--hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
|
||||||
|
--hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
|
||||||
|
--hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
|
||||||
|
--hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
|
||||||
|
--hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
|
||||||
|
--hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
|
||||||
|
--hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
|
||||||
|
--hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
|
||||||
|
--hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
|
||||||
|
--hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
|
||||||
|
--hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
|
||||||
|
--hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
|
||||||
|
--hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
|
||||||
|
--hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
|
||||||
|
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
|
||||||
|
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
|
||||||
|
# via requests
|
||||||
|
cli-base-utilities==0.10.3 \
|
||||||
|
--hash=sha256:5c54cdd5e5122abf6a86aa6926b4b2dbc6632c113885692c8d95f531bb2b181b \
|
||||||
|
--hash=sha256:95b1119d9f4bb335974faf655e853f58bdd04af0bac99d22005b6fb79b9e4b14
|
||||||
|
# via djfritz_ynh (pyproject.toml)
|
||||||
|
click==8.1.7 \
|
||||||
|
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
|
||||||
|
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
|
||||||
|
# via
|
||||||
|
# cli-base-utilities
|
||||||
|
# rich-click
|
||||||
|
colorlog==6.8.2 \
|
||||||
|
--hash=sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44 \
|
||||||
|
--hash=sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33
|
||||||
|
# via
|
||||||
|
# django-fritzconnection
|
||||||
|
# django-tools
|
||||||
|
# django-yunohost-integration
|
||||||
|
diff-match-patch==20230430 \
|
||||||
|
--hash=sha256:953019cdb9c9d2c9e47b5b12bcff3cf4746fc4598eb406076fa1fc27e6a1f15c \
|
||||||
|
--hash=sha256:dce43505fb7b1b317de7195579388df0746d90db07015ed47a85e5e44930ef93
|
||||||
|
# via django-reversion-compare
|
||||||
|
django==5.1 \
|
||||||
|
--hash=sha256:848a5980e8efb76eea70872fb0e4bc5e371619c70fffbe48e3e1b50b2c09455d \
|
||||||
|
--hash=sha256:d3b811bf5371a26def053d7ee42a9df1267ef7622323fe70a601936725aa4557
|
||||||
|
# via
|
||||||
|
# bx-django-utils
|
||||||
|
# django-admin-sortable2
|
||||||
|
# django-axes
|
||||||
|
# django-debug-toolbar
|
||||||
|
# django-fritzconnection
|
||||||
|
# django-redis
|
||||||
|
# django-reversion
|
||||||
|
# django-reversion-compare
|
||||||
|
# django-tagulous
|
||||||
|
# django-tools
|
||||||
|
# django-yunohost-integration
|
||||||
|
django-admin-sortable2==2.2.2 \
|
||||||
|
--hash=sha256:efb28eed633e3a008c6938a887096a9887a213628a39458dc748d654f8f12d5c \
|
||||||
|
--hash=sha256:fc6b62ac1e5f4c95001742d568a2c1ce371bafe9d79d809fc55779fba955e498
|
||||||
|
# via django-fritzconnection
|
||||||
|
django-axes==6.5.1 \
|
||||||
|
--hash=sha256:7435068cc8523bfa3f34faa62bb3a772b76d00925c3ff54aef43e4316e74bf05 \
|
||||||
|
--hash=sha256:d57f0fc95d581a602c642b3fe5bc31488b9401bd7441f3bec1fef0e599028499
|
||||||
|
# via
|
||||||
|
# django-fritzconnection
|
||||||
|
# django-yunohost-integration
|
||||||
|
django-debug-toolbar==4.4.6 \
|
||||||
|
--hash=sha256:36e421cb908c2f0675e07f9f41e3d1d8618dc386392ec82d23bcfcd5d29c7044 \
|
||||||
|
--hash=sha256:3beb671c9ec44ffb817fad2780667f172bd1c067dbcabad6268ce39a81335f45
|
||||||
|
# via django-fritzconnection
|
||||||
|
django-fritzconnection==0.3.0 \
|
||||||
|
--hash=sha256:4bd0ad97106b12e9e5b9013406de91948e6d2fdf92b048abef999387288872a0 \
|
||||||
|
--hash=sha256:608c387c42c505515c0b20d5b84ee5e4c8aa8773a35efd9905e14adeabd292f7
|
||||||
|
# via djfritz_ynh (pyproject.toml)
|
||||||
|
django-redis==5.4.0 \
|
||||||
|
--hash=sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42 \
|
||||||
|
--hash=sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b
|
||||||
|
# via django-yunohost-integration
|
||||||
|
django-reversion==5.1.0 \
|
||||||
|
--hash=sha256:084d4f117d9e2b4e8dfdfaad83ebb34410a03eed6071c96089e6811fdea82ad3 \
|
||||||
|
--hash=sha256:3309821e5b6fceedcce6b6975f1a9c7fab6ae7c7d0e1276a90e345946fa0dcb8
|
||||||
|
# via django-reversion-compare
|
||||||
|
django-reversion-compare==0.17.0 \
|
||||||
|
--hash=sha256:02d13ed7994d24d505671d84a005c6f99d13ed92531fa457c63245b518f835ff \
|
||||||
|
--hash=sha256:bfb036f32943965d01132809f94b853531cf6c9e3607b8894149c82fe68eddaa
|
||||||
|
# via django-fritzconnection
|
||||||
|
django-tagulous==2.0.0 \
|
||||||
|
--hash=sha256:476149f91fd0286898bf02154f0024834dd92b9d88edb6b69d5bb55d68b0b11b \
|
||||||
|
--hash=sha256:f994f04400db9742d2129eb11002bb9e41db3d76937e9ec4ffc4fe77b9beab31
|
||||||
|
# via django-fritzconnection
|
||||||
|
django-tools==0.56.2 \
|
||||||
|
--hash=sha256:29c25be814d74cd9f554d7d45bc205f5570e5feaa4232cbd09cc913c46b20c07 \
|
||||||
|
--hash=sha256:88a192f2873f0411b99ee1aba04f2779133284cd18a5c78976e8e4605ba5d7f7
|
||||||
|
# via django-yunohost-integration
|
||||||
|
django-yunohost-integration[ynh]==0.8.1 \
|
||||||
|
--hash=sha256:236bc1e427162182ca5efbf773bbad642b20741e7bf42308134887f4b7c27ced \
|
||||||
|
--hash=sha256:ced40614ba57edb0d80482e6f4f63c614115184695d2f2aaa1aa02b2485b0529
|
||||||
|
# via djfritz_ynh (pyproject.toml)
|
||||||
|
fritzconnection==1.14.0 \
|
||||||
|
--hash=sha256:95dacaf9bed6b52d809169006c0994bc55cc893dbe0a014bcf9535ae9d00982f \
|
||||||
|
--hash=sha256:f0cbc1977f21a04630773244eb1ca985af15c345aef4bbd5757b8fb124e7de1d
|
||||||
|
# via django-fritzconnection
|
||||||
|
gunicorn==23.0.0 \
|
||||||
|
--hash=sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d \
|
||||||
|
--hash=sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec
|
||||||
|
# via
|
||||||
|
# django-fritzconnection
|
||||||
|
# django-tools
|
||||||
|
# django-yunohost-integration
|
||||||
|
icdiff==2.0.7 \
|
||||||
|
--hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \
|
||||||
|
--hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f
|
||||||
|
# via django-tools
|
||||||
|
idna==3.8 \
|
||||||
|
--hash=sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac \
|
||||||
|
--hash=sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603
|
||||||
|
# via requests
|
||||||
|
markdown-it-py==3.0.0 \
|
||||||
|
--hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \
|
||||||
|
--hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb
|
||||||
|
# via rich
|
||||||
|
mdurl==0.1.2 \
|
||||||
|
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
|
||||||
|
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
|
||||||
|
# via markdown-it-py
|
||||||
|
packaging==24.1 \
|
||||||
|
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||||
|
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||||
|
# via
|
||||||
|
# cli-base-utilities
|
||||||
|
# django-yunohost-integration
|
||||||
|
# gunicorn
|
||||||
|
pprintpp==0.4.0 \
|
||||||
--hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \
|
--hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \
|
||||||
--hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403
|
--hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403
|
||||||
psycopg2==2.9.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# via django-tools
|
||||||
--hash=sha256:06f32425949bd5fe8f625c49f17ebb9784e1e4fe928b7cce72edc36fb68e4c0c \
|
psycopg[binary]==3.2.1 \
|
||||||
--hash=sha256:0762c27d018edbcb2d34d51596e4346c983bd27c330218c56c4dc25ef7e819bf \
|
--hash=sha256:dc8da6dc8729dacacda3cc2f17d2c9397a70a66cf0d2b69c91065d60d5f00cb7 \
|
||||||
--hash=sha256:083707a696e5e1c330af2508d8fab36f9700b26621ccbcb538abe22e15485362 \
|
--hash=sha256:ece385fb413a37db332f97c49208b36cf030ff02b199d7635ed2fbd378724175
|
||||||
--hash=sha256:34b33e0162cfcaad151f249c2649fd1030010c16f4bbc40a604c1cb77173dcf7 \
|
# via django-yunohost-integration
|
||||||
--hash=sha256:4295093a6ae3434d33ec6baab4ca5512a5082cc43c0505293087b8a46d108461 \
|
psycopg-binary==3.2.1 \
|
||||||
--hash=sha256:8cf3878353cc04b053822896bc4922b194792df9df2f1ad8da01fb3043602126 \
|
--hash=sha256:059cbd4e6da2337e17707178fe49464ed01de867dc86c677b30751755ec1dc51 \
|
||||||
--hash=sha256:8e841d1bf3434da985cc5ef13e6f75c8981ced601fd70cc6bf33351b91562981 \
|
--hash=sha256:06a7aae34edfe179ddc04da005e083ff6c6b0020000399a2cbf0a7121a8a22ea \
|
||||||
--hash=sha256:9572e08b50aed176ef6d66f15a21d823bb6f6d23152d35e8451d7d2d18fdac56 \
|
--hash=sha256:0879b5d76b7d48678d31278242aaf951bc2d69ca4e4d7cef117e4bbf7bfefda9 \
|
||||||
--hash=sha256:a81e3866f99382dfe8c15a151f1ca5fde5815fde879348fe5a9884a7c092a305 \
|
--hash=sha256:0ab58213cc976a1666f66bc1cb2e602315cd753b7981a8e17237ac2a185bd4a1 \
|
||||||
--hash=sha256:cb10d44e6694d763fa1078a26f7f6137d69f555a78ec85dc2ef716c37447e4b2 \
|
--hash=sha256:0b018631e5c80ce9bc210b71ea885932f9cca6db131e4df505653d7e3873a938 \
|
||||||
--hash=sha256:d3ca6421b942f60c008f81a3541e8faf6865a28d5a9b48544b0ee4f40cac7fca
|
--hash=sha256:101472468d59c74bb8565fab603e032803fd533d16be4b2d13da1bab8deb32a3 \
|
||||||
pyparsing==3.0.9 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:1d353e028b8f848b9784450fc2abf149d53a738d451eab3ee4c85703438128b9 \
|
||||||
--hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \
|
--hash=sha256:1d6833f607f3fc7b22226a9e121235d3b84c0eda1d3caab174673ef698f63788 \
|
||||||
--hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc
|
--hash=sha256:21927f41c4d722ae8eb30d62a6ce732c398eac230509af5ba1749a337f8a63e2 \
|
||||||
python-stdnum==1.17 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:28ada5f610468c57d8a4a055a8ea915d0085a43d794266c4f3b9d02f4288f4db \
|
||||||
--hash=sha256:374e2b5e13912ccdbf50b0b23fca2c3e0531174805c32d74e145f37756328340 \
|
--hash=sha256:2e8213bf50af073b1aa8dc3cff123bfeedac86332a16c1b7274910bc88a847c7 \
|
||||||
--hash=sha256:a46e6cf9652807314d369b654b255c86a59f93d18be2834f3d567ed1a346c547
|
--hash=sha256:302b86f92c0d76e99fe1b5c22c492ae519ce8b98b88d37ef74fda4c9e24c6b46 \
|
||||||
pytz==2022.4 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:334046a937bb086c36e2c6889fe327f9f29bfc085d678f70fac0b0618949f674 \
|
||||||
--hash=sha256:2c0784747071402c6e99f0bafdb7da0fa22645f06554c7ae06bf6358897e9c91 \
|
--hash=sha256:33e6669091d09f8ba36e10ce678a6d9916e110446236a9b92346464a3565635e \
|
||||||
--hash=sha256:48ce799d83b6f8aab2020e369b627446696619e79645419610b9facd909b3174
|
--hash=sha256:3c838806eeb99af39f934b7999e35f947a8e577997cc892c12b5053a97a9057f \
|
||||||
redis==4.3.4 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:40bb515d042f6a345714ec0403df68ccf13f73b05e567837d80c886c7c9d3805 \
|
||||||
--hash=sha256:a52d5694c9eb4292770084fa8c863f79367ca19884b329ab574d5cb2036b3e54 \
|
--hash=sha256:413977d18412ff83486eeb5875eb00b185a9391c57febac45b8993bf9c0ff489 \
|
||||||
--hash=sha256:ddf27071df4adf3821c4f2ca59d67525c3a82e5f268bed97b813cb4fabf87880
|
--hash=sha256:415c3b72ea32119163255c6504085f374e47ae7345f14bc3f0ef1f6e0976a879 \
|
||||||
requests==2.28.1 ; python_version >= "3.7" and python_version < "4" \
|
--hash=sha256:42781ba94e8842ee98bca5a7d0c44cc9d067500fedca2d6a90fa3609b6d16b42 \
|
||||||
--hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \
|
--hash=sha256:463d55345f73ff391df8177a185ad57b552915ad33f5cc2b31b930500c068b22 \
|
||||||
--hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349
|
--hash=sha256:4a42b8f9ab39affcd5249b45cac763ac3cf12df962b67e23fd15a2ee2932afe5 \
|
||||||
setuptools==65.4.1 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:4c84fcac8a3a3479ac14673095cc4e1fdba2935499f72c436785ac679bec0d1a \
|
||||||
--hash=sha256:1b6bdc6161661409c5f21508763dc63ab20a9ac2f8ba20029aaaa7fdb9118012 \
|
--hash=sha256:592b27d6c46a40f9eeaaeea7c1fef6f3c60b02c634365eb649b2d880669f149f \
|
||||||
--hash=sha256:3050e338e5871e70c72983072fe34f6032ae1cdeeeb67338199c2f74e083a80e
|
--hash=sha256:62b1b7b07e00ee490afb39c0a47d8282a9c2822c7cfed9553a04b0058adf7e7f \
|
||||||
six==1.16.0 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
--hash=sha256:6418712ba63cebb0c88c050b3997185b0ef54173b36568522d5634ac06153040 \
|
||||||
|
--hash=sha256:6f9e13600647087df5928875559f0eb8f496f53e6278b7da9511b4b3d0aff960 \
|
||||||
|
--hash=sha256:7066d3dca196ed0dc6172f9777b2d62e4f138705886be656cccff2d555234d60 \
|
||||||
|
--hash=sha256:73f9c9b984be9c322b5ec1515b12df1ee5896029f5e72d46160eb6517438659c \
|
||||||
|
--hash=sha256:74d623261655a169bc84a9669890975c229f2fa6e19a7f2d10a77675dcf1a707 \
|
||||||
|
--hash=sha256:788ffc43d7517c13e624c83e0e553b7b8823c9655e18296566d36a829bfb373f \
|
||||||
|
--hash=sha256:78c2007caf3c90f08685c5378e3ceb142bafd5636be7495f7d86ec8a977eaeef \
|
||||||
|
--hash=sha256:7a84b5eb194a258116154b2a4ff2962ea60ea52de089508db23a51d3d6b1c7d1 \
|
||||||
|
--hash=sha256:7ce965caf618061817f66c0906f0452aef966c293ae0933d4fa5a16ea6eaf5bb \
|
||||||
|
--hash=sha256:84837e99353d16c6980603b362d0f03302d4b06c71672a6651f38df8a482923d \
|
||||||
|
--hash=sha256:8f28ff0cb9f1defdc4a6f8c958bf6787274247e7dfeca811f6e2f56602695fb1 \
|
||||||
|
--hash=sha256:921f0c7f39590763d64a619de84d1b142587acc70fd11cbb5ba8fa39786f3073 \
|
||||||
|
--hash=sha256:950fd666ec9e9fe6a8eeb2b5a8f17301790e518953730ad44d715b59ffdbc67f \
|
||||||
|
--hash=sha256:9a997efbaadb5e1a294fb5760e2f5643d7b8e4e3fe6cb6f09e6d605fd28e0291 \
|
||||||
|
--hash=sha256:aa3931f308ab4a479d0ee22dc04bea867a6365cac0172e5ddcba359da043854b \
|
||||||
|
--hash=sha256:af0469c00f24c4bec18c3d2ede124bf62688d88d1b8a5f3c3edc2f61046fe0d7 \
|
||||||
|
--hash=sha256:b0104a72a17aa84b3b7dcab6c84826c595355bf54bb6ea6d284dcb06d99c6801 \
|
||||||
|
--hash=sha256:b09e8a576a2ac69d695032ee76f31e03b30781828b5dd6d18c6a009e5a3d1c35 \
|
||||||
|
--hash=sha256:b140182830c76c74d17eba27df3755a46442ce8d4fb299e7f1cf2f74a87c877b \
|
||||||
|
--hash=sha256:b1f087bd84bdcac78bf9f024ebdbfacd07fc0a23ec8191448a50679e2ac4a19e \
|
||||||
|
--hash=sha256:c1d2b6438fb83376f43ebb798bf0ad5e57bc56c03c9c29c85bc15405c8c0ac5a \
|
||||||
|
--hash=sha256:cad2de17804c4cfee8640ae2b279d616bb9e4734ac3c17c13db5e40982bd710d \
|
||||||
|
--hash=sha256:cc304a46be1e291031148d9d95c12451ffe783ff0cc72f18e2cc7ec43cdb8c68 \
|
||||||
|
--hash=sha256:dc314a47d44fe1a8069b075a64abffad347a3a1d8652fed1bab5d3baea37acb2 \
|
||||||
|
--hash=sha256:f092114f10f81fb6bae544a0ec027eb720e2d9c74a4fcdaa9dd3899873136935 \
|
||||||
|
--hash=sha256:f34e369891f77d0738e5d25727c307d06d5344948771e5379ea29c76c6d84555 \
|
||||||
|
--hash=sha256:f8a509aeaac364fa965454e80cd110fe6d48ba2c80f56c9b8563423f0b5c3cfd \
|
||||||
|
--hash=sha256:f8afb07114ea9b924a4a0305ceb15354ccf0ef3c0e14d54b8dbeb03e50182dd7 \
|
||||||
|
--hash=sha256:f99e59f8a5f4dcd9cbdec445f3d8ac950a492fc0e211032384d6992ed3c17eb7
|
||||||
|
# via psycopg
|
||||||
|
pygments==2.18.0 \
|
||||||
|
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
|
||||||
|
--hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a
|
||||||
|
# via rich
|
||||||
|
python-dateutil==2.9.0.post0 \
|
||||||
|
--hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
|
||||||
|
--hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
|
||||||
|
# via cli-base-utilities
|
||||||
|
python-stdnum==1.20 \
|
||||||
|
--hash=sha256:111008e10391d54fb2afad2a10df70d5cb0c6c0a7ec82fec6f022cb8712961d3 \
|
||||||
|
--hash=sha256:ad2a2cf2eb025de408210235f36b4ae31252de3186240ccaa8126e117cb82690
|
||||||
|
# via bx-django-utils
|
||||||
|
pyyaml==6.0.2 \
|
||||||
|
--hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
|
||||||
|
--hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
|
||||||
|
--hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
|
||||||
|
--hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
|
||||||
|
--hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
|
||||||
|
--hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
|
||||||
|
--hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
|
||||||
|
--hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
|
||||||
|
--hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
|
||||||
|
--hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
|
||||||
|
--hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
|
||||||
|
--hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
|
||||||
|
--hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
|
||||||
|
--hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
|
||||||
|
--hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
|
||||||
|
--hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
|
||||||
|
--hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
|
||||||
|
--hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
|
||||||
|
--hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
|
||||||
|
--hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
|
||||||
|
--hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
|
||||||
|
--hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
|
||||||
|
--hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
|
||||||
|
--hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
|
||||||
|
--hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
|
||||||
|
--hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
|
||||||
|
--hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
|
||||||
|
--hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
|
||||||
|
--hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
|
||||||
|
--hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
|
||||||
|
--hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
|
||||||
|
--hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
|
||||||
|
--hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
|
||||||
|
--hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
|
||||||
|
--hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
|
||||||
|
--hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
|
||||||
|
--hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
|
||||||
|
--hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
|
||||||
|
--hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
|
||||||
|
--hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
|
||||||
|
--hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
|
||||||
|
--hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
|
||||||
|
--hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
|
||||||
|
--hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
|
||||||
|
--hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
|
||||||
|
--hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
|
||||||
|
--hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
|
||||||
|
--hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
|
||||||
|
--hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
|
||||||
|
--hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
|
||||||
|
--hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
|
||||||
|
--hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
|
||||||
|
--hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
|
||||||
|
# via django-yunohost-integration
|
||||||
|
redis==5.0.8 \
|
||||||
|
--hash=sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870 \
|
||||||
|
--hash=sha256:56134ee08ea909106090934adc36f65c9bcbbaecea5b21ba704ba6fb561f8eb4
|
||||||
|
# via django-redis
|
||||||
|
requests==2.32.3 \
|
||||||
|
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||||
|
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
|
||||||
|
# via fritzconnection
|
||||||
|
rich==13.8.0 \
|
||||||
|
--hash=sha256:2e85306a063b9492dffc86278197a60cbece75bcb766022f3436f567cae11bdc \
|
||||||
|
--hash=sha256:a5ac1f1cd448ade0d59cc3356f7db7a7ccda2c8cbae9c7a90c28ff463d3e91f4
|
||||||
|
# via
|
||||||
|
# cli-base-utilities
|
||||||
|
# django-reversion-compare
|
||||||
|
# rich-click
|
||||||
|
rich-click==1.8.3 \
|
||||||
|
--hash=sha256:636d9c040d31c5eee242201b5bf4f2d358bfae4db14bb22ec1cafa717cfd02cd \
|
||||||
|
--hash=sha256:6d75bdfa7aa9ed2c467789a0688bc6da23fbe3a143e19aa6ad3f8bac113d2ab3
|
||||||
|
# via cli-base-utilities
|
||||||
|
six==1.16.0 \
|
||||||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||||
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
|
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
|
||||||
sqlparse==0.4.3 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# via
|
||||||
--hash=sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34 \
|
# bleach
|
||||||
--hash=sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268
|
# python-dateutil
|
||||||
typing-extensions==4.3.0 ; python_version >= "3.7" and python_version < "3.8" \
|
sqlparse==0.5.1 \
|
||||||
--hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \
|
--hash=sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4 \
|
||||||
--hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6
|
--hash=sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e
|
||||||
urllib3==1.26.12 ; python_version >= "3.7" and python_version < "4" \
|
# via
|
||||||
--hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \
|
# django
|
||||||
--hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
|
# django-debug-toolbar
|
||||||
webencodings==0.5.1 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
tomli==2.0.1 \
|
||||||
|
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
|
||||||
|
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
|
||||||
|
# via cli-base-utilities
|
||||||
|
tomlkit==0.13.2 \
|
||||||
|
--hash=sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde \
|
||||||
|
--hash=sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79
|
||||||
|
# via cli-base-utilities
|
||||||
|
typing-extensions==4.12.2 \
|
||||||
|
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||||
|
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||||
|
# via
|
||||||
|
# psycopg
|
||||||
|
# rich-click
|
||||||
|
urllib3==2.2.2 \
|
||||||
|
--hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
|
||||||
|
--hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
|
||||||
|
# via requests
|
||||||
|
webencodings==0.5.1 \
|
||||||
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
||||||
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
|
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
|
||||||
wrapt==1.14.1 ; python_version >= "3.7" and python_full_version < "4.0.0" \
|
# via bleach
|
||||||
--hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \
|
|
||||||
--hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \
|
|
||||||
--hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \
|
|
||||||
--hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \
|
|
||||||
--hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \
|
|
||||||
--hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \
|
|
||||||
--hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \
|
|
||||||
--hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \
|
|
||||||
--hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \
|
|
||||||
--hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \
|
|
||||||
--hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \
|
|
||||||
--hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \
|
|
||||||
--hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \
|
|
||||||
--hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \
|
|
||||||
--hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \
|
|
||||||
--hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \
|
|
||||||
--hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \
|
|
||||||
--hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \
|
|
||||||
--hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \
|
|
||||||
--hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \
|
|
||||||
--hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \
|
|
||||||
--hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \
|
|
||||||
--hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \
|
|
||||||
--hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \
|
|
||||||
--hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \
|
|
||||||
--hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \
|
|
||||||
--hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \
|
|
||||||
--hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \
|
|
||||||
--hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \
|
|
||||||
--hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \
|
|
||||||
--hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \
|
|
||||||
--hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \
|
|
||||||
--hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \
|
|
||||||
--hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \
|
|
||||||
--hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \
|
|
||||||
--hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \
|
|
||||||
--hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \
|
|
||||||
--hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \
|
|
||||||
--hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \
|
|
||||||
--hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \
|
|
||||||
--hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \
|
|
||||||
--hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \
|
|
||||||
--hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \
|
|
||||||
--hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \
|
|
||||||
--hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \
|
|
||||||
--hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \
|
|
||||||
--hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \
|
|
||||||
--hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \
|
|
||||||
--hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \
|
|
||||||
--hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \
|
|
||||||
--hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \
|
|
||||||
--hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \
|
|
||||||
--hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \
|
|
||||||
--hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \
|
|
||||||
--hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \
|
|
||||||
--hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \
|
|
||||||
--hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \
|
|
||||||
--hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \
|
|
||||||
--hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \
|
|
||||||
--hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \
|
|
||||||
--hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \
|
|
||||||
--hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \
|
|
||||||
--hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \
|
|
||||||
--hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af
|
|
||||||
zipp==3.8.1 ; python_version >= "3.7" and python_version < "3.8" \
|
|
||||||
--hash=sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2 \
|
|
||||||
--hash=sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
# Please do not modify this file, it will be reset at the next update.
|
# Please do not modify this file, it will be reset at the next update.
|
||||||
# You can edit the file __INSTALL_DIR__/local_settings.py and add/modify the settings you need.
|
# You can edit the file __DATA_DIR__/local_settings.py and add/modify the settings you need.
|
||||||
# The parameters you add in local_settings.py will overwrite these,
|
# The parameters you add in local_settings.py will overwrite these,
|
||||||
# but you can use the options and documentation in this file to find out what can be done.
|
# but you can use the options and documentation in this file to find out what can be done.
|
||||||
|
|
||||||
|
@ -14,29 +14,33 @@ 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
|
||||||
from django_yunohost_integration.secret_key import get_or_create_secret as __get_or_create_secret
|
from django_yunohost_integration.secret_key import get_or_create_secret as __get_or_create_secret
|
||||||
|
|
||||||
from djfritz_project.settings.base import * # noqa:F401,F403
|
|
||||||
|
# https://github.com/jedie/django-fritzconnection
|
||||||
|
from djfritz_project.settings.prod import * # noqa:F401,F403 isort:skip
|
||||||
|
|
||||||
|
|
||||||
from django_yunohost_integration.base_settings import LOGGING # noqa:F401 isort:skip
|
from django_yunohost_integration.base_settings import LOGGING # noqa:F401 isort:skip
|
||||||
|
|
||||||
|
|
||||||
INSTALL_DIR = __Path('__INSTALL_DIR__/app') # /var/www/$app/app
|
DATA_DIR_PATH = __Path('__DATA_DIR__') # /home/yunohost.app/$app/
|
||||||
assert INSTALL_DIR.is_dir(), f'Directory not exists: {INSTALL_DIR}'
|
assert DATA_DIR_PATH.is_dir(), f'Directory not exists: {DATA_DIR_PATH}'
|
||||||
|
|
||||||
PUBLIC_PATH = __Path('__INSTALL_DIR__/public') # /var/www/$app/public
|
INSTALL_DIR_PATH = __Path('__INSTALL_DIR__') # /var/www/$app/
|
||||||
assert PUBLIC_PATH.is_dir(), f'Directory not exists: {PUBLIC_PATH}'
|
assert INSTALL_DIR_PATH.is_dir(), f'Directory not exists: {INSTALL_DIR_PATH}'
|
||||||
|
|
||||||
LOG_FILE = __Path('/var/log/__APP__/__APP__.log') # /var/log/$app/$app.log
|
LOG_FILE_PATH = __Path('__LOG_FILE__') # /var/log/$app/djfritz_ynh.log
|
||||||
assert LOG_FILE.is_file(), f'File not exists: {LOG_FILE}'
|
assert LOG_FILE_PATH.is_file(), f'File not exists: {LOG_FILE_PATH}'
|
||||||
|
|
||||||
PATH = '__PATH__' # $YNH_APP_ARG_PATH
|
PATH_URL = '__PATH__'
|
||||||
PATH = PATH.strip('/')
|
PATH_URL = PATH_URL.strip('/')
|
||||||
|
|
||||||
|
YNH_CURRENT_HOST = '__YNH_CURRENT_HOST__' # YunoHost main domain from: /etc/yunohost/current_host
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# config_panel.toml settings:
|
# config_panel.toml settings:
|
||||||
|
|
||||||
DEBUG_ENABLED = '__DEBUG_ENABLED__'
|
DEBUG_ENABLED = '__DEBUG_ENABLED__'
|
||||||
DEBUG = bool(int(DEBUG_ENABLED))
|
DEBUG = DEBUG_ENABLED == '1'
|
||||||
|
|
||||||
LOG_LEVEL = '__LOG_LEVEL__'
|
LOG_LEVEL = '__LOG_LEVEL__'
|
||||||
ADMIN_EMAIL = '__ADMIN_EMAIL__'
|
ADMIN_EMAIL = '__ADMIN_EMAIL__'
|
||||||
|
@ -48,20 +52,26 @@ DEFAULT_FROM_EMAIL = '__DEFAULT_FROM_EMAIL__'
|
||||||
# Function that will be called to finalize a user profile:
|
# Function that will be called to finalize a user profile:
|
||||||
YNH_SETUP_USER = 'setup_user.setup_project_user'
|
YNH_SETUP_USER = 'setup_user.setup_project_user'
|
||||||
|
|
||||||
SECRET_KEY = __get_or_create_secret(INSTALL_DIR / 'secret.txt') # /opt/yunohost/$app/secret.txt
|
|
||||||
|
|
||||||
INSTALLED_APPS += [
|
if 'axes' not in INSTALLED_APPS:
|
||||||
'axes', # https://github.com/jazzband/django-axes
|
INSTALLED_APPS.append('axes') # https://github.com/jazzband/django-axes
|
||||||
'django_yunohost_integration', # https://github.com/YunoHost-Apps/django_yunohost_integration
|
|
||||||
]
|
INSTALLED_APPS.append('django_yunohost_integration.apps.YunohostIntegrationConfig')
|
||||||
|
|
||||||
|
|
||||||
|
SECRET_KEY = __get_or_create_secret(
|
||||||
|
DATA_DIR_PATH / 'secret.txt'
|
||||||
|
) # /home/yunohost.app/$app/secret.txt
|
||||||
|
|
||||||
|
|
||||||
MIDDLEWARE.insert(
|
MIDDLEWARE.insert(
|
||||||
MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware') + 1,
|
MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware') + 1,
|
||||||
# login a user via HTTP_REMOTE_USER header from SSOwat:
|
# login a user via HTTP_REMOTE_USER header from SSOwat:
|
||||||
'django_yunohost_integration.sso_auth.auth_middleware.SSOwatRemoteUserMiddleware',
|
'django_yunohost_integration.sso_auth.auth_middleware.SSOwatRemoteUserMiddleware',
|
||||||
)
|
)
|
||||||
# AxesMiddleware should be the last middleware:
|
if 'axes.middleware.AxesMiddleware' not in MIDDLEWARE:
|
||||||
MIDDLEWARE.append('axes.middleware.AxesMiddleware')
|
# AxesMiddleware should be the last middleware:
|
||||||
|
MIDDLEWARE.append('axes.middleware.AxesMiddleware')
|
||||||
|
|
||||||
|
|
||||||
# Keep ModelBackend around for per-user permissions and superuser
|
# Keep ModelBackend around for per-user permissions and superuser
|
||||||
|
@ -126,6 +136,9 @@ CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django_redis.cache.RedisCache',
|
'BACKEND': 'django_redis.cache.RedisCache',
|
||||||
'LOCATION': 'redis://127.0.0.1:6379/__REDIS_DB__',
|
'LOCATION': 'redis://127.0.0.1:6379/__REDIS_DB__',
|
||||||
|
# If redis is running on same host as django-fritzconnection, you might
|
||||||
|
# want to use unix sockets instead:
|
||||||
|
# 'LOCATION': 'unix:///var/run/redis/redis.sock?db=1',
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
||||||
},
|
},
|
||||||
|
@ -136,29 +149,30 @@ CACHES = {
|
||||||
# _____________________________________________________________________________
|
# _____________________________________________________________________________
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
|
||||||
if PATH:
|
if PATH_URL:
|
||||||
STATIC_URL = f'/{PATH}/static/'
|
STATIC_URL = f'/{PATH_URL}/static/'
|
||||||
MEDIA_URL = f'/{PATH}/media/'
|
MEDIA_URL = f'/{PATH_URL}/media/'
|
||||||
else:
|
else:
|
||||||
# Installed to domain root, without a path prefix?
|
# Installed to domain root, without a path prefix?
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
MEDIA_URL = '/media/'
|
MEDIA_URL = '/media/'
|
||||||
|
|
||||||
STATIC_ROOT = str(PUBLIC_PATH / 'static')
|
STATIC_ROOT = str(INSTALL_DIR_PATH / 'static')
|
||||||
MEDIA_ROOT = str(PUBLIC_PATH / 'media')
|
MEDIA_ROOT = str(INSTALL_DIR_PATH / 'media')
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
# Set log file to e.g.: /var/log/$app/$app.log
|
# Set log file to e.g.: /var/log/$app/$app.log
|
||||||
LOGGING['handlers']['log_file']['filename'] = str(LOG_FILE)
|
LOGGING['handlers']['log_file']['filename'] = str(LOG_FILE_PATH)
|
||||||
|
|
||||||
# Example how to add logging to own app:
|
# Example how to add logging to own app:
|
||||||
LOGGING['loggers']['djfritz'] = {
|
LOGGING['loggers']['djfritz'] = {
|
||||||
'handlers': ['syslog', 'log_file', 'mail_admins'],
|
'handlers': ['syslog', 'log_file', 'mail_admins'],
|
||||||
'level': 'INFO',
|
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
}
|
}
|
||||||
|
for __logger_name in LOGGING['loggers'].keys():
|
||||||
|
LOGGING['loggers'][__logger_name]['level'] = 'DEBUG' if DEBUG else LOG_LEVEL
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ After=redis.service postgresql.service
|
||||||
[Service]
|
[Service]
|
||||||
User=__APP__
|
User=__APP__
|
||||||
Group=__APP__
|
Group=__APP__
|
||||||
WorkingDirectory=__INSTALL_DIR__/app
|
WorkingDirectory=__DATA_DIR__/
|
||||||
|
|
||||||
ExecStart=__INSTALL_DIR__/venv/bin/gunicorn --config __INSTALL_DIR__/app/gunicorn.conf.py wsgi
|
ExecStart=__DATA_DIR__/venv/bin/gunicorn --config __DATA_DIR__/gunicorn.conf.py wsgi
|
||||||
|
|
||||||
StandardOutput=syslog
|
StandardOutput=syslog
|
||||||
StandardError=syslog
|
StandardError=syslog
|
||||||
|
|
10
conf/urls.py
10
conf/urls.py
|
@ -6,13 +6,15 @@
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
|
|
||||||
if settings.PATH:
|
if settings.PATH_URL:
|
||||||
# settings.PATH is the $YNH_APP_ARG_PATH
|
# settings.PATH_URL is __PATH__
|
||||||
# Prefix all urls with "PATH":
|
# Prefix all urls with "PATH_URL":
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(f'{settings.PATH}/', include('djfritz_project.urls')),
|
path('', RedirectView.as_view(url=f'{settings.PATH_URL}/')),
|
||||||
|
path(f'{settings.PATH_URL}/', include('djfritz_project.urls')),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
# Installed to domain root, without a path prefix
|
# Installed to domain root, without a path prefix
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# https://yunohost.org/en/packaging_config_panels
|
||||||
# https://github.com/YunoHost/example_ynh/blob/master/config_panel.toml.example
|
# https://github.com/YunoHost/example_ynh/blob/master/config_panel.toml.example
|
||||||
|
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
@ -14,25 +15,28 @@ services = ["__APP__"]
|
||||||
ask = "from email"
|
ask = "from email"
|
||||||
type = "email"
|
type = "email"
|
||||||
help = "Default email address to use for various automated emails."
|
help = "Default email address to use for various automated emails."
|
||||||
bind = "default_from_email:__INSTALL_DIR__/app/settings.py"
|
#
|
||||||
|
# We can't use "__DATA_DIR__" in bind value, because of this bug:
|
||||||
|
# https://github.com/YunoHost/issues/issues/2283
|
||||||
|
bind = "default_from_email:/home/yunohost.app/__APP__/settings.py"
|
||||||
|
|
||||||
[main.config.admin_email]
|
[main.config.admin_email]
|
||||||
ask = "ADMIN email"
|
ask = "ADMIN email"
|
||||||
type = "email"
|
type = "email"
|
||||||
help = "EMail address for error emails."
|
help = "EMail address for error emails."
|
||||||
bind = "admin_email:__INSTALL_DIR__/app/settings.py"
|
bind = "admin_email:/home/yunohost.app/__APP__/settings.py"
|
||||||
|
|
||||||
[main.config.debug_enabled]
|
[main.config.debug_enabled]
|
||||||
ask = "DEBUG mode"
|
ask = "DEBUG mode"
|
||||||
type = "boolean"
|
type = "boolean"
|
||||||
yes = "1"
|
yes = "1"
|
||||||
no = "0"
|
no = "0"
|
||||||
help = "Should be never enabled in production!"
|
help = "Enable DEBUG mode? (Should be never enabled in production!)"
|
||||||
bind = "debug_enabled:__INSTALL_DIR__/app/settings.py"
|
bind = "debug_enabled:/home/yunohost.app/__APP__/settings.py"
|
||||||
|
|
||||||
[main.config.log_level]
|
[main.config.log_level]
|
||||||
type = "string"
|
type = "string"
|
||||||
ask = "Log Level"
|
ask = "Log Level"
|
||||||
choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
||||||
default = "WARNING"
|
default = "WARNING"
|
||||||
bind = "log_level:__INSTALL_DIR__/app/settings.py"
|
bind = "log_level:/home/yunohost.app/__APP__/settings.py"
|
||||||
|
|
116
dev-cli.py
Executable file
116
dev-cli.py
Executable file
|
@ -0,0 +1,116 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
bootstrap CLI
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Just call this file, and the magic happens ;)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import venv
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def print_no_pip_error():
|
||||||
|
print('Error: Pip not available!')
|
||||||
|
print('Hint: "apt-get install python3-venv"\n')
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ensurepip import version
|
||||||
|
except ModuleNotFoundError as err:
|
||||||
|
print(err)
|
||||||
|
print('-' * 100)
|
||||||
|
print_no_pip_error()
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
if not version():
|
||||||
|
print_no_pip_error()
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
assert sys.version_info >= (3, 11), f'Python version {sys.version_info} is too old!'
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform == 'win32': # wtf
|
||||||
|
# Files under Windows, e.g.: .../.venv/Scripts/python.exe
|
||||||
|
BIN_NAME = 'Scripts'
|
||||||
|
FILE_EXT = '.exe'
|
||||||
|
else:
|
||||||
|
# Files under Linux/Mac and all other than Windows, e.g.: .../.venv/bin/python
|
||||||
|
BIN_NAME = 'bin'
|
||||||
|
FILE_EXT = ''
|
||||||
|
|
||||||
|
BASE_PATH = Path(__file__).parent
|
||||||
|
VENV_PATH = BASE_PATH / '.venv'
|
||||||
|
BIN_PATH = VENV_PATH / BIN_NAME
|
||||||
|
PYTHON_PATH = BIN_PATH / f'python3{FILE_EXT}'
|
||||||
|
PIP_PATH = BIN_PATH / f'pip{FILE_EXT}'
|
||||||
|
PIP_SYNC_PATH = BIN_PATH / f'pip-sync{FILE_EXT}'
|
||||||
|
|
||||||
|
DEP_LOCK_PATH = BASE_PATH / 'requirements.dev.txt'
|
||||||
|
DEP_HASH_PATH = VENV_PATH / '.dep_hash'
|
||||||
|
|
||||||
|
# script file defined in pyproject.toml as [console_scripts]
|
||||||
|
# (Under Windows: ".exe" not added!)
|
||||||
|
PROJECT_SHELL_SCRIPT = BIN_PATH / 'djfritz_ynh_dev'
|
||||||
|
|
||||||
|
|
||||||
|
def get_dep_hash():
|
||||||
|
"""Get SHA512 hash from lock file content."""
|
||||||
|
return hashlib.sha512(DEP_LOCK_PATH.read_bytes()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def store_dep_hash():
|
||||||
|
"""Generate .venv/.dep_hash"""
|
||||||
|
DEP_HASH_PATH.write_text(get_dep_hash())
|
||||||
|
|
||||||
|
|
||||||
|
def venv_up2date():
|
||||||
|
"""Is existing .venv is up-to-date?"""
|
||||||
|
if DEP_HASH_PATH.is_file():
|
||||||
|
return DEP_HASH_PATH.read_text() == get_dep_hash()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def verbose_check_call(*popen_args):
|
||||||
|
print(f'\n+ {shlex.join(str(arg) for arg in popen_args)}\n')
|
||||||
|
return subprocess.check_call(popen_args)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
assert DEP_LOCK_PATH.is_file(), f'File not found: "{DEP_LOCK_PATH}" !'
|
||||||
|
|
||||||
|
# Create virtual env in ".venv/":
|
||||||
|
if not PYTHON_PATH.is_file():
|
||||||
|
print(f'Create virtual env here: {VENV_PATH.absolute()}')
|
||||||
|
builder = venv.EnvBuilder(symlinks=True, upgrade=True, with_pip=True)
|
||||||
|
builder.create(env_dir=VENV_PATH)
|
||||||
|
|
||||||
|
if not PROJECT_SHELL_SCRIPT.is_file() or not venv_up2date():
|
||||||
|
# Update pip
|
||||||
|
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip')
|
||||||
|
|
||||||
|
# Install pip-tools
|
||||||
|
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip-tools')
|
||||||
|
|
||||||
|
# install requirements via "pip-sync"
|
||||||
|
verbose_check_call(PIP_SYNC_PATH, str(DEP_LOCK_PATH))
|
||||||
|
|
||||||
|
# install project
|
||||||
|
verbose_check_call(PIP_PATH, 'install', '--no-deps', '-e', '.')
|
||||||
|
store_dep_hash()
|
||||||
|
|
||||||
|
# Call our entry point CLI:
|
||||||
|
try:
|
||||||
|
verbose_check_call(PROJECT_SHELL_SCRIPT, *argv[1:])
|
||||||
|
except subprocess.CalledProcessError as err:
|
||||||
|
sys.exit(err.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv)
|
7
djfritz_ynh/__init__.py
Normal file
7
djfritz_ynh/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
djfritz_ynh
|
||||||
|
Web based FritzBox management using Python/Django.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = '0.3.0+ynh4'
|
||||||
|
__author__ = 'Jens Diemer <git@jensdiemer.de>'
|
0
djfritz_ynh/cli/__init__.py
Normal file
0
djfritz_ynh/cli/__init__.py
Normal file
301
djfritz_ynh/cli/dev.py
Normal file
301
djfritz_ynh/cli/dev.py
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
"""
|
||||||
|
CLI for development
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import shlex
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import rich_click as click
|
||||||
|
from cli_base.cli_tools import code_style
|
||||||
|
from cli_base.cli_tools.dev_tools import run_coverage, run_tox
|
||||||
|
from cli_base.cli_tools.subprocess_utils import verbose_check_call
|
||||||
|
from cli_base.cli_tools.test_utils.snapshot import UpdateTestSnapshotFiles
|
||||||
|
from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE
|
||||||
|
from cli_base.cli_tools.version_info import print_version
|
||||||
|
from cli_base.run_pip_audit import run_pip_audit
|
||||||
|
from django.core.management.commands.test import Command as DjangoTestCommand
|
||||||
|
from django_yunohost_integration.local_test import create_local_test
|
||||||
|
from django_yunohost_integration.path_utils import get_project_root
|
||||||
|
from manageprojects.utilities.publish import publish_package
|
||||||
|
from rich import print
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.traceback import install as rich_traceback_install
|
||||||
|
from rich_click import RichGroup
|
||||||
|
|
||||||
|
import djfritz_ynh
|
||||||
|
from djfritz_ynh import constants
|
||||||
|
from djfritz_ynh.tests import setup_ynh_tests
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
OPTION_ARGS_DEFAULT_TRUE = dict(is_flag=True, show_default=True, default=True)
|
||||||
|
OPTION_ARGS_DEFAULT_FALSE = dict(is_flag=True, show_default=True, default=False)
|
||||||
|
ARGUMENT_EXISTING_DIR = dict(
|
||||||
|
type=click.Path(exists=True, file_okay=False, dir_okay=True, readable=True, path_type=Path)
|
||||||
|
)
|
||||||
|
ARGUMENT_NOT_EXISTING_DIR = dict(
|
||||||
|
type=click.Path(
|
||||||
|
exists=False,
|
||||||
|
file_okay=False,
|
||||||
|
dir_okay=True,
|
||||||
|
readable=False,
|
||||||
|
writable=True,
|
||||||
|
path_type=Path,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ARGUMENT_EXISTING_FILE = dict(
|
||||||
|
type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True, path_type=Path)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier?
|
||||||
|
def make_context(self, info_name, *args, **kwargs):
|
||||||
|
info_name = './dev-cli.py'
|
||||||
|
return super().make_context(info_name, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@click.group(
|
||||||
|
cls=ClickGroup,
|
||||||
|
epilog=constants.CLI_EPILOG,
|
||||||
|
)
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE)
|
||||||
|
def mypy(verbosity: int):
|
||||||
|
"""Run Mypy (configured in pyproject.toml)"""
|
||||||
|
verbose_check_call('mypy', '.', cwd=get_project_root(), verbose=verbosity > 0, exit_on_error=True)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def install():
|
||||||
|
"""
|
||||||
|
Run pip-sync and install 'djfritz_ynh' via pip as editable.
|
||||||
|
"""
|
||||||
|
verbose_check_call('pip-sync', get_project_root() / 'requirements.dev.txt')
|
||||||
|
verbose_check_call('pip', 'install', '--no-deps', '-e', '.')
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE)
|
||||||
|
def pip_audit(verbosity: int):
|
||||||
|
"""
|
||||||
|
Run pip-audit check against current requirements files
|
||||||
|
"""
|
||||||
|
run_pip_audit(base_path=get_project_root(), verbosity=verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def update():
|
||||||
|
"""
|
||||||
|
Update "requirements*.txt" dependencies files
|
||||||
|
"""
|
||||||
|
bin_path = Path(sys.executable).parent
|
||||||
|
|
||||||
|
verbose_check_call(bin_path / 'pip', 'install', '-U', 'pip')
|
||||||
|
verbose_check_call(bin_path / 'pip', 'install', '-U', 'pip-tools')
|
||||||
|
|
||||||
|
extra_env = dict(
|
||||||
|
CUSTOM_COMPILE_COMMAND='./dev-cli.py update',
|
||||||
|
)
|
||||||
|
|
||||||
|
pip_compile_base = [
|
||||||
|
bin_path / 'pip-compile',
|
||||||
|
'--verbose',
|
||||||
|
'--allow-unsafe', # https://pip-tools.readthedocs.io/en/latest/#deprecations
|
||||||
|
'--resolver=backtracking', # https://pip-tools.readthedocs.io/en/latest/#deprecations
|
||||||
|
'--upgrade',
|
||||||
|
'--generate-hashes',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Only "prod" dependencies:
|
||||||
|
verbose_check_call(
|
||||||
|
*pip_compile_base,
|
||||||
|
'pyproject.toml',
|
||||||
|
'--output-file',
|
||||||
|
'conf/requirements.txt',
|
||||||
|
extra_env=extra_env,
|
||||||
|
)
|
||||||
|
|
||||||
|
# dependencies + "dev"-optional-dependencies:
|
||||||
|
verbose_check_call(
|
||||||
|
*pip_compile_base,
|
||||||
|
'pyproject.toml',
|
||||||
|
'--extra=dev',
|
||||||
|
'--output-file',
|
||||||
|
'requirements.dev.txt',
|
||||||
|
extra_env=extra_env,
|
||||||
|
)
|
||||||
|
|
||||||
|
run_pip_audit(base_path=get_project_root())
|
||||||
|
|
||||||
|
# Install new dependencies in current .venv:
|
||||||
|
verbose_check_call(bin_path / 'pip-sync', 'requirements.dev.txt')
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def publish():
|
||||||
|
"""
|
||||||
|
Build and upload this project to PyPi
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
_run_django_test_cli(argv=sys.argv, exit_after_run=True) # Don't publish a broken state
|
||||||
|
except SystemExit as err:
|
||||||
|
assert err.code == 0, f'Exit code is not 0: {err.code}'
|
||||||
|
|
||||||
|
publish_package(
|
||||||
|
module=djfritz_ynh,
|
||||||
|
package_path=get_project_root(),
|
||||||
|
distribution_name='djfritz_ynh',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('--color/--no-color', **OPTION_ARGS_DEFAULT_TRUE)
|
||||||
|
@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE)
|
||||||
|
def fix_code_style(color: bool, verbosity: int):
|
||||||
|
"""
|
||||||
|
Fix code style of all your_cool_package source code files via darker
|
||||||
|
"""
|
||||||
|
code_style.fix(package_root=get_project_root(), darker_color=color, darker_verbose=verbosity > 0)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option('--color/--no-color', **OPTION_ARGS_DEFAULT_TRUE)
|
||||||
|
@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE)
|
||||||
|
def check_code_style(color: bool, verbosity: int):
|
||||||
|
"""
|
||||||
|
Check code style by calling darker + flake8
|
||||||
|
"""
|
||||||
|
code_style.check(package_root=get_project_root(), darker_color=color, darker_verbose=verbosity > 0)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def update_test_snapshot_files():
|
||||||
|
"""
|
||||||
|
Update all test snapshot files (by remove and recreate all snapshot files)
|
||||||
|
"""
|
||||||
|
with UpdateTestSnapshotFiles(root_path=get_project_root(), verbose=True):
|
||||||
|
# Just recreate them by running tests:
|
||||||
|
_run_django_test_cli(argv=sys.argv, exit_after_run=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _run_django_test_cli(argv, exit_after_run=True):
|
||||||
|
"""
|
||||||
|
Call the origin Django test manage command CLI and pass all args to it.
|
||||||
|
"""
|
||||||
|
setup_ynh_tests()
|
||||||
|
|
||||||
|
print('\nStart Django unittests with:')
|
||||||
|
for default_arg in ('shuffle', 'buffer'):
|
||||||
|
if default_arg not in argv and f'--no-{default_arg}' not in argv:
|
||||||
|
argv.append(f'--{default_arg}')
|
||||||
|
print(shlex.join(argv))
|
||||||
|
print()
|
||||||
|
|
||||||
|
test_command = DjangoTestCommand()
|
||||||
|
|
||||||
|
test_command.run_from_argv(argv)
|
||||||
|
if exit_after_run:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command() # Dummy command
|
||||||
|
def test():
|
||||||
|
"""
|
||||||
|
Compile YunoHost files and run Django unittests
|
||||||
|
"""
|
||||||
|
_run_django_test_cli(argv=sys.argv, exit_after_run=True)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command() # Dummy command
|
||||||
|
def coverage():
|
||||||
|
"""
|
||||||
|
Run tests and show coverage report.
|
||||||
|
"""
|
||||||
|
run_coverage()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command() # Dummy "tox" command
|
||||||
|
def tox():
|
||||||
|
"""
|
||||||
|
Run tox
|
||||||
|
"""
|
||||||
|
run_tox()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def version():
|
||||||
|
"""Print version and exit"""
|
||||||
|
# Pseudo command, because the version always printed on every CLI call ;)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def local_test():
|
||||||
|
"""
|
||||||
|
Build a "local_test" YunoHost installation and start the Django dev. server against it.
|
||||||
|
"""
|
||||||
|
create_local_test(
|
||||||
|
django_settings_path=get_project_root() / 'conf' / 'settings.py',
|
||||||
|
destination=get_project_root() / 'local_test',
|
||||||
|
runserver=True,
|
||||||
|
extra_replacements={
|
||||||
|
'__DEBUG_ENABLED__': '1',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def diffsettings():
|
||||||
|
"""
|
||||||
|
Run "diffsettings" manage command against a "local_test" YunoHost installation.
|
||||||
|
"""
|
||||||
|
destination = get_project_root() / 'local_test'
|
||||||
|
create_local_test(
|
||||||
|
django_settings_path=get_project_root() / 'conf' / 'settings.py',
|
||||||
|
destination=destination,
|
||||||
|
runserver=False,
|
||||||
|
extra_replacements={
|
||||||
|
'__DEBUG_ENABLED__': '1',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
app_path = destination / 'opt_yunohost'
|
||||||
|
verbose_check_call(
|
||||||
|
sys.executable,
|
||||||
|
app_path / 'manage.py',
|
||||||
|
'diffsettings',
|
||||||
|
cwd=app_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print_version(djfritz_ynh)
|
||||||
|
|
||||||
|
if len(sys.argv) >= 2:
|
||||||
|
# Check if we can just pass a command call to origin CLI:
|
||||||
|
command = sys.argv[1]
|
||||||
|
command_map = {
|
||||||
|
'test': _run_django_test_cli,
|
||||||
|
'tox': run_tox,
|
||||||
|
'coverage': run_coverage,
|
||||||
|
}
|
||||||
|
if real_func := command_map.get(command):
|
||||||
|
real_func(argv=sys.argv, exit_after_run=True)
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
rich_traceback_install(
|
||||||
|
width=console.size.width, # full terminal width
|
||||||
|
show_locals=True,
|
||||||
|
suppress=[click],
|
||||||
|
max_frames=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
print('Execute Click CLI')
|
||||||
|
cli()
|
3
djfritz_ynh/constants.py
Normal file
3
djfritz_ynh/constants.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
CLI_EPILOG = 'Project Homepage: https://github.com/YunoHost-Apps/django-fritzconnection_ynh'
|
70
djfritz_ynh/tests/__init__.py
Normal file
70
djfritz_ynh/tests/__init__.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest.util
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import django
|
||||||
|
from bx_py_utils.test_utils.deny_requests import deny_any_real_request
|
||||||
|
from cli_base.cli_tools.verbosity import MAX_LOG_LEVEL, setup_logging
|
||||||
|
from django_yunohost_integration.local_test import CreateResults, create_local_test
|
||||||
|
from django_yunohost_integration.path_utils import get_project_root
|
||||||
|
from rich import print # noqa
|
||||||
|
from typeguard import install_import_hook
|
||||||
|
|
||||||
|
|
||||||
|
# Check type annotations via typeguard in all tests:
|
||||||
|
install_import_hook(packages=('djfritz_ynh',))
|
||||||
|
|
||||||
|
|
||||||
|
def pre_configure_tests() -> None:
|
||||||
|
print(f'Configure unittests via "load_tests Protocol" from {Path(__file__).relative_to(Path.cwd())}')
|
||||||
|
|
||||||
|
# Hacky way to display more "assert"-Context in failing tests:
|
||||||
|
_MIN_MAX_DIFF = unittest.util._MAX_LENGTH - unittest.util._MIN_DIFF_LEN
|
||||||
|
unittest.util._MAX_LENGTH = int(os.environ.get('UNITTEST_MAX_LENGTH', 300))
|
||||||
|
unittest.util._MIN_DIFF_LEN = unittest.util._MAX_LENGTH - _MIN_MAX_DIFF
|
||||||
|
|
||||||
|
# Deny any request via docket/urllib3 because tests they should mock all requests:
|
||||||
|
deny_any_real_request()
|
||||||
|
|
||||||
|
# Display DEBUG logs in tests:
|
||||||
|
setup_logging(verbosity=MAX_LOG_LEVEL)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_ynh_tests() -> None:
|
||||||
|
# Import after "install_import_hook" to check type annotations:
|
||||||
|
import djfritz_ynh
|
||||||
|
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||||
|
|
||||||
|
print('Compile YunoHost files...')
|
||||||
|
result: CreateResults = create_local_test(
|
||||||
|
django_settings_path=get_project_root() / 'conf' / 'settings.py',
|
||||||
|
destination=get_project_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)
|
||||||
|
|
||||||
|
data_dir = str(result.data_dir_path)
|
||||||
|
if data_dir not in sys.path:
|
||||||
|
sys.path.insert(0, data_dir)
|
||||||
|
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
os.chdir(Path(djfritz_ynh.__file__).parent)
|
||||||
|
|
||||||
|
|
||||||
|
def load_tests(loader, tests, pattern):
|
||||||
|
"""
|
||||||
|
Use unittest "load_tests Protocol" as a hook to setup test environment before running tests.
|
||||||
|
https://docs.python.org/3/library/unittest.html#load-tests-protocol
|
||||||
|
"""
|
||||||
|
pre_configure_tests()
|
||||||
|
return loader.discover(start_dir=Path(__file__).parent, pattern=pattern)
|
169
djfritz_ynh/tests/test_django_project.py
Normal file
169
djfritz_ynh/tests/test_django_project.py
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from axes.models import AccessLog
|
||||||
|
from bx_django_utils.test_utils.html_assertion import HtmlAssertionMixin
|
||||||
|
from django.conf import LazySettings, settings
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.template.defaulttags import CsrfTokenNode
|
||||||
|
from django.test import override_settings
|
||||||
|
from django.test.testcases import TestCase
|
||||||
|
from django.urls.base import reverse
|
||||||
|
from django_yunohost_integration.test_utils import generate_basic_auth
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(DEBUG=False)
|
||||||
|
class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
# Always start a fresh session:
|
||||||
|
self.client = self.client_class()
|
||||||
|
|
||||||
|
def test_settings(self):
|
||||||
|
assert isinstance(settings, LazySettings)
|
||||||
|
assert settings.configured is True
|
||||||
|
|
||||||
|
assert settings.PATH_URL == 'app_path'
|
||||||
|
|
||||||
|
assert str(settings.DATA_DIR_PATH).endswith('/local_test/opt_yunohost'), f'{settings.DATA_DIR_PATH=}'
|
||||||
|
assert str(settings.INSTALL_DIR_PATH).endswith('/local_test/var_www'), f'{settings.INSTALL_DIR_PATH=}'
|
||||||
|
assert str(settings.LOG_FILE_PATH).endswith(
|
||||||
|
'/local_test/var_log_django-fritzconnection.log'
|
||||||
|
), f'{settings.LOG_FILE_PATH=}'
|
||||||
|
|
||||||
|
assert settings.ROOT_URLCONF == 'urls'
|
||||||
|
|
||||||
|
def test_config_panel_settings(self):
|
||||||
|
# config_panel.toml settings, set via tests.conftest.pytest_configure():
|
||||||
|
assert settings.DEBUG_ENABLED == '0' and settings.DEBUG is False
|
||||||
|
assert settings.LOG_LEVEL == 'INFO'
|
||||||
|
assert settings.ADMIN_EMAIL == 'foo-bar@test.tld'
|
||||||
|
assert settings.DEFAULT_FROM_EMAIL == 'django_app@test.tld'
|
||||||
|
|
||||||
|
def test_auth(self):
|
||||||
|
assert settings.PATH_URL == 'app_path'
|
||||||
|
self.assertEqual(reverse('admin:index'), '/app_path/admin/')
|
||||||
|
|
||||||
|
# SecurityMiddleware should redirects all non-HTTPS requests to HTTPS:
|
||||||
|
assert settings.SECURE_SSL_REDIRECT is True
|
||||||
|
response = self.client.get('/app_path/admin/', secure=False)
|
||||||
|
self.assertRedirects(
|
||||||
|
response,
|
||||||
|
status_code=301, # permanent redirect
|
||||||
|
expected_url='https://testserver/app_path/admin/',
|
||||||
|
fetch_redirect_response=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get('/app_path/admin/', secure=True)
|
||||||
|
self.assertRedirects(
|
||||||
|
response,
|
||||||
|
expected_url='/app_path/admin/login/?next=%2Fapp_path%2Fadmin%2F',
|
||||||
|
fetch_redirect_response=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_unknown_user(self):
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
|
||||||
|
self.client.cookies['SSOwAuthUser'] = 'test'
|
||||||
|
|
||||||
|
with patch.object(CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'):
|
||||||
|
response = self.client.get(
|
||||||
|
path='/app_path/admin/',
|
||||||
|
HTTP_REMOTE_USER='test',
|
||||||
|
HTTP_AUTH_USER='test',
|
||||||
|
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||||
|
secure=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
user = User.objects.first()
|
||||||
|
assert user.username == 'test'
|
||||||
|
assert user.is_active is True
|
||||||
|
assert user.is_staff is True # Set by: conf.setup_user.setup_project_user
|
||||||
|
assert user.is_superuser is False
|
||||||
|
|
||||||
|
self.assert_html_parts(
|
||||||
|
response,
|
||||||
|
parts=(
|
||||||
|
'<h1>Site administration</h1>',
|
||||||
|
'<strong>test</strong>',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
# TODO: assert_html_response_snapshot(response, query_selector='#container', validate=False)
|
||||||
|
|
||||||
|
def test_wrong_auth_user(self):
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
assert AccessLog.objects.count() == 0
|
||||||
|
|
||||||
|
self.client.cookies['SSOwAuthUser'] = 'test'
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
path='/app_path/admin/',
|
||||||
|
HTTP_REMOTE_USER='test',
|
||||||
|
HTTP_AUTH_USER='foobar', # <<< wrong user name
|
||||||
|
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||||
|
secure=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
user = User.objects.first()
|
||||||
|
assert user.username == 'test'
|
||||||
|
assert user.is_active is True
|
||||||
|
assert user.is_staff is True # Set by: conf.setup_user.setup_project_user
|
||||||
|
assert user.is_superuser is False
|
||||||
|
|
||||||
|
assert AccessLog.objects.count() == 1
|
||||||
|
|
||||||
|
assert response.status_code == 403 # Forbidden
|
||||||
|
|
||||||
|
def test_wrong_cookie(self):
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
assert AccessLog.objects.count() == 0
|
||||||
|
|
||||||
|
self.client.cookies['SSOwAuthUser'] = 'foobar' # <<< wrong user name
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
path='/app_path/',
|
||||||
|
HTTP_REMOTE_USER='test',
|
||||||
|
HTTP_AUTH_USER='test',
|
||||||
|
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||||
|
secure=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
user = User.objects.first()
|
||||||
|
assert user.username == 'test'
|
||||||
|
assert user.is_active is True
|
||||||
|
assert user.is_staff is True # Set by: conf.setup_user.setup_project_user
|
||||||
|
assert user.is_superuser is False
|
||||||
|
|
||||||
|
assert AccessLog.objects.count() == 1
|
||||||
|
|
||||||
|
assert response.status_code == 403 # Forbidden
|
||||||
|
|
||||||
|
def test_wrong_authorization_user(self):
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
|
||||||
|
self.client.cookies['SSOwAuthUser'] = 'test'
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
path='/app_path/',
|
||||||
|
HTTP_REMOTE_USER='test',
|
||||||
|
HTTP_AUTH_USER='test',
|
||||||
|
HTTP_AUTHORIZATION=generate_basic_auth(
|
||||||
|
username='foobar', # <<< wrong user name
|
||||||
|
password='test123',
|
||||||
|
),
|
||||||
|
secure=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert User.objects.count() == 1
|
||||||
|
user = User.objects.first()
|
||||||
|
assert user.username == 'test'
|
||||||
|
assert user.is_active is True
|
||||||
|
assert user.is_staff is True # Set by: conf.setup_user.setup_project_user
|
||||||
|
assert user.is_superuser is False
|
||||||
|
|
||||||
|
assert AccessLog.objects.count() == 1
|
||||||
|
|
||||||
|
assert response.status_code == 403 # Forbidden
|
10
djfritz_ynh/tests/test_doctests.py
Normal file
10
djfritz_ynh/tests/test_doctests.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from bx_py_utils.test_utils.unittest_utils import BaseDocTests
|
||||||
|
|
||||||
|
import djfritz_ynh
|
||||||
|
|
||||||
|
|
||||||
|
class DocTests(BaseDocTests):
|
||||||
|
def test_doctests(self):
|
||||||
|
self.run_doctests(
|
||||||
|
modules=(djfritz_ynh,),
|
||||||
|
)
|
89
djfritz_ynh/tests/test_project_setup.py
Normal file
89
djfritz_ynh/tests/test_project_setup.py
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
import 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.path_utils import get_project_root
|
||||||
|
from djfritz import __version__ as upstream_version
|
||||||
|
|
||||||
|
from djfritz_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):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
|
||||||
|
manifest_path = get_project_root() / 'manifest.toml'
|
||||||
|
assert_is_file(manifest_path)
|
||||||
|
|
||||||
|
cls.manifest_cfg = tomllib.loads(manifest_path.read_text(encoding='UTF-8'))
|
||||||
|
|
||||||
|
def test_version(self):
|
||||||
|
assert ynh_pkg_version.startswith(
|
||||||
|
upstream_version
|
||||||
|
), f'{ynh_pkg_version=} does not start with {upstream_version=}'
|
||||||
|
self.assertIn('+ynh', ynh_pkg_version)
|
||||||
|
|
||||||
|
# pyproject.toml needs a PEP 440 conform version and used "+ynh"
|
||||||
|
# the YunoHost syntax is: "~ynh", just "convert this:
|
||||||
|
manifest_version = ynh_pkg_version.replace('+', '~')
|
||||||
|
self.assertEqual(self.manifest_cfg['version'], manifest_version)
|
||||||
|
|
||||||
|
def test_screenshot_filenames(self):
|
||||||
|
"""
|
||||||
|
https://forum.yunohost.org/t/yunohost-bot-cant-handle-spaces-in-screenshots/19483
|
||||||
|
"""
|
||||||
|
screenshot_path = get_project_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(self):
|
||||||
|
check_editor_config(package_root=get_project_root())
|
||||||
|
|
||||||
|
def test_manifest_toml(self):
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
)
|
38
djfritz_ynh/tests/test_readme.py
Normal file
38
djfritz_ynh/tests/test_readme.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from bx_py_utils.auto_doc import assert_readme_block
|
||||||
|
from django_yunohost_integration.path_utils import get_project_root
|
||||||
|
from manageprojects.test_utils.click_cli_utils import invoke_click
|
||||||
|
from manageprojects.tests.base import BaseTestCase
|
||||||
|
|
||||||
|
from djfritz_ynh.cli.dev import cli
|
||||||
|
from djfritz_ynh.constants import CLI_EPILOG
|
||||||
|
|
||||||
|
|
||||||
|
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=get_project_root() / 'doc' / 'ADMIN.md',
|
||||||
|
)
|
148
doc/ADMIN.md
148
doc/ADMIN.md
|
@ -1,130 +1,60 @@
|
||||||
## Settings and upgrades
|
## Settings and upgrades
|
||||||
|
|
||||||
Almost everything related to django-fritzconnection's configuration is handled in a `"../conf/settings.py"` file.
|
Almost everything related to django-fritzconnection's configuration is handled in a `"../conf/settings.py"` file.
|
||||||
You can edit the file `/var/www/django-fritzconnection/app/local_settings.py` to enable or disable features.
|
You can edit the file `/home/yunohost.app/django-fritzconnection/local_settings.py` to enable or disable features.
|
||||||
|
|
||||||
Test sending emails:
|
Test sending emails, e.g.:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh admin@yourdomain.tld
|
ssh admin@yourdomain.tld
|
||||||
root@yunohost:~# cd /var/www/django-fritzconnection/
|
root@yunohost:~# /home/yunohost.app/django-fritzconnection/manage.py sendtestemail --admins
|
||||||
root@yunohost:/var/www/django-fritzconnection# source venv/bin/activate
|
|
||||||
(venv) root@yunohost:/var/www/django-fritzconnection# ./app/manage.py sendtestemail --admins
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Background info: Error mails are send to all [settings.ADMINS](https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-ADMINS). By default the YunoHost admin is inserted here.
|
How to debug a django YunoHost app, take a look into:
|
||||||
To check current ADMINS run:
|
|
||||||
|
|
||||||
```bash
|
* https://github.com/YunoHost-Apps/django-fritzconnection_ynh#developer-info
|
||||||
(venv) root@yunohost:/var/www/django-fritzconnection# ./app/manage.py sendtestemail --admins
|
|
||||||
```
|
|
||||||
|
|
||||||
If you prefere to send error emails to a extrnal email address, just do something like this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "ADMINS = (('Your Name', 'example@domain.tld'),)" >> /var/www/django-fritzconnection/app/local_settings.py
|
|
||||||
```
|
|
||||||
|
|
||||||
To check the effective settings, run this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
(venv) root@yunohost:/var/www/django-fritzconnection# ./app/manage.py diffsettings
|
|
||||||
```
|
|
||||||
|
|
||||||
# Miscellaneous
|
|
||||||
|
|
||||||
## SSO authentication
|
|
||||||
|
|
||||||
[SSOwat](https://github.com/YunoHost/SSOwat) is fully supported via [django-yunohost-integration](https://github.com/YunoHost-Apps/django_yunohost_integration):
|
|
||||||
|
|
||||||
* First user (`$YNH_APP_ARG_ADMIN`) will be created as Django's super user
|
|
||||||
* All new users will be created as normal users
|
|
||||||
* Login via SSO is fully supported
|
|
||||||
* User Email, First / Last name will be updated from SSO data
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Yunohost developer commands
|
|
||||||
|
|
||||||
To remove call e.g.:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo yunohost app remove django-fritzconnection
|
|
||||||
```
|
|
||||||
|
|
||||||
Backup / remove / restore cycle, e.g.:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yunohost backup create --apps django-fritzconnection
|
|
||||||
yunohost backup list
|
|
||||||
archives:
|
|
||||||
- django-fritzconnection-pre-upgrade1
|
|
||||||
- 20201223-163434
|
|
||||||
yunohost app remove django-fritzconnection
|
|
||||||
yunohost backup restore 20201223-163434 --apps django-fritzconnection
|
|
||||||
```
|
|
||||||
|
|
||||||
Debug installation, e.g.:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
root@yunohost:~# ls -la /var/www/django-fritzconnection/
|
|
||||||
total 18
|
|
||||||
drwxr-xr-x 4 root root 4 Dec 8 08:36 .
|
|
||||||
drwxr-xr-x 6 root root 6 Dec 8 08:36 ..
|
|
||||||
drwxr-xr-x 2 root root 2 Dec 8 08:36 media
|
|
||||||
drwxr-xr-x 7 root root 8 Dec 8 08:40 static
|
|
||||||
|
|
||||||
root@yunohost:~# ls -la /var/www/django-fritzconnection/
|
|
||||||
total 58
|
|
||||||
drwxr-xr-x 5 django-fritzconnection django-fritzconnection 11 Dec 8 08:39 .
|
|
||||||
drwxr-xr-x 3 root root 3 Dec 8 08:36 ..
|
|
||||||
-rw-r--r-- 1 django-fritzconnection django-fritzconnection 460 Dec 8 08:39 gunicorn.conf.py
|
|
||||||
-rw-r--r-- 1 django-fritzconnection django-fritzconnection 0 Dec 8 08:39 local_settings.py
|
|
||||||
-rwxr-xr-x 1 django-fritzconnection django-fritzconnection 274 Dec 8 08:39 manage.py
|
|
||||||
-rw-r--r-- 1 django-fritzconnection django-fritzconnection 171 Dec 8 08:39 secret.txt
|
|
||||||
drwxr-xr-x 6 django-fritzconnection django-fritzconnection 6 Dec 8 08:37 venv
|
|
||||||
-rw-r--r-- 1 django-fritzconnection django-fritzconnection 115 Dec 8 08:39 wsgi.py
|
|
||||||
-rw-r--r-- 1 django-fritzconnection django-fritzconnection 4737 Dec 8 08:39 settings.py
|
|
||||||
|
|
||||||
root@yunohost:~# cd /var/www/django-fritzconnection/
|
|
||||||
root@yunohost:/var/www/django-fritzconnection# source venv/bin/activate
|
|
||||||
(venv) root@yunohost:/var/www/django-fritzconnection# ./manage.py check
|
|
||||||
django-fritzconnection v0.8.2 (Django v2.2.17)
|
|
||||||
DJANGO_SETTINGS_MODULE='settings'
|
|
||||||
PROJECT_PATH:/var/www/django-fritzconnection/venv/lib/python3.7/site-packages
|
|
||||||
BASE_PATH:/var/www/django-fritzconnection
|
|
||||||
System check identified no issues (0 silenced).
|
|
||||||
|
|
||||||
root@yunohost:~# tail -f /var/log/django-fritzconnection/django-fritzconnection.log
|
|
||||||
root@yunohost:~# cat /etc/systemd/system/django-fritzconnection.service
|
|
||||||
|
|
||||||
root@yunohost:~# systemctl reload-or-restart django-fritzconnection
|
|
||||||
root@yunohost:~# journalctl --unit=django-fritzconnection --follow
|
|
||||||
```
|
|
||||||
|
|
||||||
## local test
|
## local test
|
||||||
|
|
||||||
For quicker developing of django-fritzconnection in the context of YunoHost app,
|
For quicker developing of djfritz_ynh in the context of YunoHost app,
|
||||||
it's possible to run the Django developer server with the settings
|
it's possible to run the Django developer server with the settings
|
||||||
and urls made for YunoHost installation.
|
and urls made for YunoHost installation.
|
||||||
|
|
||||||
e.g.:
|
e.g.:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ git clone https://github.com/YunoHost-Apps/django-fritzconnection_ynh.git
|
~$ git clone https://github.com/YunoHost-Apps/django-fritzconnection.git
|
||||||
~$ cd django-fritzconnection_ynh/
|
~$ cd djfritz_ynh/
|
||||||
~/django-fritzconnection_ynh$ make
|
~/django-fritzconnection$ ./dev-cli.py --help
|
||||||
install-poetry install or update poetry
|
|
||||||
install install django-fritzconnection via poetry
|
|
||||||
update update the sources and installation
|
|
||||||
local-test Run local_test.py to run django-fritzconnection_ynh locally
|
|
||||||
~/django-fritzconnection_ynh$ make install-poetry
|
|
||||||
~/django-fritzconnection_ynh$ make install
|
|
||||||
~/django-fritzconnection_ynh$ make local-test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
* SQlite database will be used
|
The output will looks like:
|
||||||
* A super user with username `test` and password `test` is created
|
|
||||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
[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 tests and show coverage report. │
|
||||||
|
│ diffsettings Run "diffsettings" manage command against a "local_test" YunoHost │
|
||||||
|
│ installation. │
|
||||||
|
│ fix-code-style Fix code style of all your_cool_package source code files via darker │
|
||||||
|
│ install Run pip-sync and install 'djfritz_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) │
|
||||||
|
│ pip-audit Run pip-audit check against current requirements files │
|
||||||
|
│ publish Build and upload this project to PyPi │
|
||||||
|
│ 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 ✂✂✂)
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
Web based FritzBox management using Python/Django and the great [fritzconnection](https://github.com/kbr/fritzconnection) library.
|
Web based FritzBox management using Python/Django and the great [fritzconnection](https://github.com/kbr/fritzconnection) library.
|
||||||
|
[![tests](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/tests.yml)
|
||||||
|
[![codecov](https://codecov.io/github/jedie/djfritz_ynh/branch/main/graph/badge.svg)](https://app.codecov.io/github/jedie/djfritz_ynh)
|
||||||
|
[![djfritz_ynh @ PyPi](https://img.shields.io/pypi/v/djfritz_ynh?label=djfritz_ynh%20%40%20PyPi)](https://pypi.org/project/djfritz_ynh/)
|
||||||
|
[![Python Versions](https://img.shields.io/pypi/pyversions/djfritz_ynh)](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/blob/main/pyproject.toml)
|
||||||
|
[![License GPL-3.0-or-later](https://img.shields.io/pypi/l/djfritz_ynh)](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/blob/main/LICENSE)
|
||||||
|
|
||||||
The basic idea is to block/unblock Internet access to a group of devices as easily as possible.
|
|
||||||
|
|
||||||
|
|
||||||
[![pytest](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/pytest.yml/badge.svg?branch=master)](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/pytest.yml) [![YunoHost apps package linter](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/package_linter.yml/badge.svg)](https://github.com/YunoHost-Apps/django-fritzconnection_ynh/actions/workflows/package_linter.yml) [![Coverage Status on codecov.io](https://codecov.io/gh/YunoHost-Apps/django-fritzconnection_ynh/branch/master/graph/badge.svg)](https://codecov.io/gh/YunoHost-Apps/django-fritzconnection_ynh)
|
|
||||||
|
|
||||||
![django-fritzconnection @ PyPi](https://img.shields.io/pypi/v/django-fritzconnection?label=django-fritzconnection%20%40%20PyPi)
|
|
||||||
![Python Versions](https://img.shields.io/pypi/pyversions/django-fritzconnection)
|
|
||||||
![License GPL V3+](https://img.shields.io/pypi/l/django-fritzconnection)
|
|
||||||
|
|
||||||
Pull requests welcome ;)
|
Pull requests welcome ;)
|
||||||
|
|
||||||
|
|
25
local_settings_source.py
Normal file
25
local_settings_source.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# This file will be copied to the "local test" files, to overwrite Django settings
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
print('Load local settings file:', __file__)
|
||||||
|
|
||||||
|
ENV_TYPE = os.environ.get('ENV_TYPE', None)
|
||||||
|
print(f'ENV_TYPE: {ENV_TYPE!r}')
|
||||||
|
|
||||||
|
if ENV_TYPE == 'local':
|
||||||
|
print(f'Activate settings overwrite by {__file__}')
|
||||||
|
SECURE_SSL_REDIRECT = False # Don't redirect http to https
|
||||||
|
SERVE_FILES = True # May used in urls.py
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [] # accept all passwords
|
||||||
|
ALLOWED_HOSTS = ['127.0.0.1', 'localhost'] # For local dev. server
|
||||||
|
CACHES = { # Setup a working cache, without Redis ;)
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
'LOCATION': 'unique-snowflake',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
elif ENV_TYPE == 'test':
|
||||||
|
SILENCED_SYSTEM_CHECKS = ['security.W018'] # tests runs with DEBUG=True
|
||||||
|
ALLOWED_HOSTS = [] # For unittests (Django's setup_test_environment() will add 'testserver')
|
11
manage_local_test.py
Normal file
11
manage_local_test.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#!.venv/bin/python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Call the "manage.py" from the local test environment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django_yunohost_integration.local_test import run_local_test_manage
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run_local_test_manage()
|
|
@ -1,66 +1,112 @@
|
||||||
#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json
|
# https://yunohost.org/en/packaging_manifest
|
||||||
|
|
||||||
packaging_format = 2
|
packaging_format = 2
|
||||||
|
|
||||||
id = "django-fritzconnection"
|
id = "django-fritzconnection"
|
||||||
name = "django-fritzconnection"
|
name = "django-fritzconnection"
|
||||||
description.en = "Web based FritzBox management using Python/Django."
|
description.en = "Web based FritzBox management using Python/Django."
|
||||||
|
|
||||||
version = "0.2.0~ynh3"
|
version = "0.3.0~ynh4"
|
||||||
|
|
||||||
maintainers = ["Jens Diemer"]
|
maintainers = ["Jens Diemer"]
|
||||||
|
|
||||||
|
|
||||||
[upstream]
|
[upstream]
|
||||||
license = "GPL-3.0"
|
# https://yunohost.org/en/packaging_manifest#upstream-section
|
||||||
code = "https://github.com/jedie/django-fritzconnection"
|
license = "GPL-3.0-or-later"
|
||||||
|
# website = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh" # If the app has no proper website, just remove the 'website' key entirely
|
||||||
|
admindoc = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
||||||
|
userdoc = "https://github.com/jedie/django-fritzconnection"
|
||||||
|
code = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[integration]
|
[integration]
|
||||||
yunohost = ">= 11.2.12"
|
# https://yunohost.org/en/packaging_manifest#integration-section
|
||||||
|
yunohost = ">=11.2"
|
||||||
architectures = "all"
|
architectures = "all"
|
||||||
multi_instance = true
|
multi_instance = true
|
||||||
ldap = true
|
ldap = true
|
||||||
sso = true
|
sso = true
|
||||||
disk = "100M"
|
disk = "50M" # **estimate** minimum disk requirement. e.g. 20M, 400M, 1G, ...
|
||||||
ram.build = "500M"
|
ram.build = "50M" # **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ...
|
||||||
ram.runtime = "100M"
|
ram.runtime = "50M" # **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
|
# https://yunohost.org/en/packaging_manifest#install-questions
|
||||||
|
|
||||||
[install.domain]
|
[install.domain]
|
||||||
|
# this is a generic question - ask strings are automatically handled by Yunohost's core
|
||||||
type = "domain"
|
type = "domain"
|
||||||
|
|
||||||
[install.path]
|
[install.path]
|
||||||
|
# this is a generic question - ask strings are automatically handled by Yunohost's core
|
||||||
|
# setting $path and template variable __PATH__
|
||||||
type = "path"
|
type = "path"
|
||||||
default = "/django-fritzconnection"
|
default = "/djfritz_ynh"
|
||||||
|
|
||||||
|
[install.admin]
|
||||||
|
# this is a generic question - ask strings are automatically handled by Yunohost's core
|
||||||
|
type = "user"
|
||||||
|
default = "admin"
|
||||||
|
|
||||||
[install.init_main_permission]
|
[install.init_main_permission]
|
||||||
type = "group"
|
type = "group"
|
||||||
default = "visitors"
|
default = "admins"
|
||||||
|
|
||||||
|
[install.default_from_email] # __DEFAULT_FROM_EMAIL__
|
||||||
|
ask.en = "Default email address to use for various automated emails."
|
||||||
|
type = "email"
|
||||||
|
example = "admin@example.com"
|
||||||
|
|
||||||
|
[install.admin_email] # __ADMIN_EMAIL__
|
||||||
|
ask.en = "EMail address for error emails."
|
||||||
|
type = "email"
|
||||||
|
example = "admin@example.com"
|
||||||
|
|
||||||
|
[install.debug_enabled] # __DEBUG_ENABLED__ will be set to "0" or "1" string
|
||||||
|
ask.en = "Should be never enabled in production!"
|
||||||
|
type = "boolean"
|
||||||
|
|
||||||
|
[install.log_level] # __LOG_LEVEL__
|
||||||
|
ask.en = "Logging level"
|
||||||
|
type = "select"
|
||||||
|
choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
||||||
|
default = "WARNING"
|
||||||
|
|
||||||
[install.admin]
|
|
||||||
type = "user"
|
|
||||||
|
|
||||||
[resources]
|
[resources]
|
||||||
[resources.system_user]
|
[resources.system_user]
|
||||||
|
# This will provision/deprovision a unix system user
|
||||||
|
|
||||||
[resources.install_dir]
|
[resources.install_dir]
|
||||||
|
# https://yunohost.org/en/packaging_apps_resources#install-dir
|
||||||
|
# This will create/remove the install dir as /var/www/$app/
|
||||||
|
# and store the corresponding setting $install_dir and template variable __INSTALL_DIR__
|
||||||
|
|
||||||
|
[resources.data_dir]
|
||||||
|
# https://yunohost.org/en/packaging_apps_resources#data-dir
|
||||||
|
# This will create/remove the data dir as /home/yunohost.app/$app/
|
||||||
|
# and store the corresponding setting $data_dir and template variable __DATA_DIR__
|
||||||
|
|
||||||
[resources.permissions]
|
[resources.permissions]
|
||||||
|
# https://yunohost.org/en/packaging_apps_resources#permissions
|
||||||
|
# This will configure SSOwat permission for $domain/$path/
|
||||||
|
# The initial allowed group of user is configured via the init_main_permission question (public=visitors, private=all_users)
|
||||||
main.url = "/"
|
main.url = "/"
|
||||||
|
|
||||||
[resources.ports]
|
[resources.ports]
|
||||||
|
# https://yunohost.org/en/packaging_apps_resources#ports
|
||||||
|
# This will pick a random port for reverse-proxying and store it as the $port setting
|
||||||
|
|
||||||
[resources.apt]
|
[resources.apt]
|
||||||
packages = [
|
# https://yunohost.org/en/packaging_apps_resources#apt
|
||||||
"build-essential",
|
# This will automatically install/uninstall the following apt packages
|
||||||
"python3-dev",
|
packages = "build-essential, python3-dev, python3-pip, python3-venv, git, libffi-dev, libpq-dev, postgresql, postgresql-contrib, redis-server, checkinstall, pkg-config, libssl-dev, openssl"
|
||||||
"python3-pip",
|
|
||||||
"python3-venv",
|
|
||||||
"git",
|
|
||||||
"libpq-dev",
|
|
||||||
"postgresql",
|
|
||||||
"postgresql-contrib",
|
|
||||||
"redis-server",
|
|
||||||
]
|
|
||||||
|
|
||||||
[resources.database]
|
[resources.database]
|
||||||
|
# https://yunohost.org/en/packaging_apps_resources#database
|
||||||
|
# This will automatically provision/deprovison a Postgres DB
|
||||||
|
# and store the corresponding credentials in settings $db_user, $db_name, $db_pwd
|
||||||
type = "postgresql"
|
type = "postgresql"
|
||||||
|
|
1462
poetry.lock
generated
1462
poetry.lock
generated
File diff suppressed because it is too large
Load diff
216
pyproject.toml
216
pyproject.toml
|
@ -1,49 +1,94 @@
|
||||||
[tool.poetry]
|
[project]
|
||||||
name = "django-fritzconnection_ynh"
|
name = "djfritz_ynh"
|
||||||
version = "0.2.0+ynh2"
|
dynamic = ["version"]
|
||||||
description = "Test django-fritzconnection_ynh via local_test.py"
|
description = "Web based FritzBox management using Python/Django."
|
||||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
license = {text = "GPL-3.0-or-later"}
|
||||||
license = "GPL"
|
readme = "README.md"
|
||||||
homepage = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
authors = [
|
||||||
|
{name = 'Jens Diemer', email = 'git@jensdiemer.de'}
|
||||||
|
]
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
dependencies = [
|
||||||
|
"django-fritzconnection", # https://github.com/jedie/django-fritzconnection
|
||||||
|
#
|
||||||
|
# extras "ynh" will install: gunicorn, psycopg2, django-redis and django-axes
|
||||||
|
# see: https://github.com/YunoHost-Apps/django_yunohost_integration/blob/main/pyproject.toml
|
||||||
|
"django_yunohost_integration[ynh]", # https://github.com/YunoHost-Apps/django_yunohost_integration
|
||||||
|
#
|
||||||
|
"cli-base-utilities", # https://github.com/jedie/cli-base-utilities
|
||||||
|
]
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"bx_django_utils", # https://github.com/boxine/bx_django_utils
|
||||||
|
"beautifulsoup4", # https://pypi.org/project/beautifulsoup4/
|
||||||
|
"manageprojects", # https://github.com/jedie/manageprojects
|
||||||
|
"pip-tools", # https://github.com/jazzband/pip-tools/
|
||||||
|
"tblib", # https://github.com/ionelmc/python-tblib
|
||||||
|
"tox", # https://github.com/tox-dev/tox
|
||||||
|
"coverage", # https://github.com/nedbat/coveragepy
|
||||||
|
"autopep8", # https://github.com/hhatto/autopep8
|
||||||
|
"pyupgrade", # https://github.com/asottile/pyupgrade
|
||||||
|
"flake8", # https://github.com/pycqa/flake8
|
||||||
|
"flake8-bugbear", # https://github.com/PyCQA/flake8-bugbear
|
||||||
|
"pyflakes", # https://github.com/PyCQA/pyflakes
|
||||||
|
"codespell", # https://github.com/codespell-project/codespell
|
||||||
|
"EditorConfig", # https://github.com/editorconfig/editorconfig-core-py
|
||||||
|
"pip-audit", # https://github.com/pypa/pip-audit
|
||||||
|
"mypy", # https://github.com/python/mypy
|
||||||
|
"twine", # https://github.com/pypa/twine
|
||||||
|
"typeguard", # https://github.com/agronholm/typeguard/
|
||||||
|
|
||||||
[tool.poetry.urls]
|
# https://github.com/akaihola/darker
|
||||||
"Bug Tracker" = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh/issues"
|
# https://github.com/ikamensh/flynt
|
||||||
|
# https://github.com/pycqa/isort
|
||||||
|
# https://github.com/pygments/pygments
|
||||||
|
"darker[flynt, isort, color]",
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
# Work-a-round for: https://github.com/jazzband/pip-tools/issues/1866
|
||||||
python = ">=3.7,<4.0.0" # TODO: Update to >=3.8 after YunoHost updates to Bullseye
|
# see also: https://github.com/jazzband/pip-tools/issues/994#issuecomment-1321226661
|
||||||
django-fritzconnection = ">=0.2.0"
|
# backports.tarfile is needed for python <3.12
|
||||||
|
'backports.tarfile', # via jaraco-context -> keyring -> twine
|
||||||
|
]
|
||||||
|
|
||||||
# extras "ynh" will install: gunicorn, psycopg2, django-redis and django-axes
|
[project.urls]
|
||||||
# see: https://github.com/YunoHost-Apps/django_yunohost_integration/blob/main/pyproject.toml
|
Documentation = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
||||||
django_yunohost_integration = {version = ">=0.4.1", extras = ["ynh"]} # https://github.com/YunoHost-Apps/django_yunohost_integration
|
Source = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[project.scripts]
|
||||||
bx_py_utils = "*" # https://github.com/boxine/bx_py_utils
|
djfritz_ynh_app = "djfritz_ynh.__main__:main"
|
||||||
bx_django_utils = "*" # https://github.com/boxine/bx_django_utils
|
djfritz_ynh_dev = "djfritz_ynh.cli.dev:main"
|
||||||
tox = "*"
|
|
||||||
pytest = "*"
|
|
||||||
pytest-cov = "*"
|
[ynh-integration]
|
||||||
pytest-django = "*"
|
local_settings_source= "local_settings_source.py"
|
||||||
pytest-darker = "*" # https://github.com/akaihola/pytest-darker
|
|
||||||
coveralls = "*"
|
|
||||||
isort = "*"
|
|
||||||
flake8 = "*"
|
|
||||||
EditorConfig = "*" # https://github.com/editorconfig/editorconfig-core-py
|
|
||||||
safety = "*" # https://github.com/pyupio/safety
|
|
||||||
requests = "*" # https://github.com/psf/requests
|
|
||||||
packaging = "*" # https://github.com/pypa/packagi
|
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["setuptools>=61.0", "setuptools_scm>=7.1"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["."]
|
||||||
|
include = ["djfritz_ynh*"]
|
||||||
|
|
||||||
|
[tool.setuptools.dynamic]
|
||||||
|
version = {attr = "djfritz_ynh.__version__"}
|
||||||
|
|
||||||
|
|
||||||
|
[tool.cli_base.pip_audit]
|
||||||
|
# https://github.com/jedie/cli-base-utilities/blob/main/docs/pip_audit.md
|
||||||
|
requirements=["requirements.dev.txt"]
|
||||||
|
strict=true
|
||||||
|
require_hashes=true
|
||||||
|
ignore-vuln=[]
|
||||||
|
|
||||||
|
|
||||||
[tool.darker]
|
[tool.darker]
|
||||||
src = ['.']
|
src = ['.']
|
||||||
|
# YunoHost apps still use "master" istead of "main", isn't it?
|
||||||
revision = "origin/master..."
|
revision = "origin/master..."
|
||||||
line_length = 100
|
line_length = 119
|
||||||
verbose = true
|
color = true
|
||||||
skip_string_normalization = true
|
skip_string_normalization = true
|
||||||
diff = false
|
diff = false
|
||||||
check = false
|
check = false
|
||||||
|
@ -59,54 +104,85 @@ log_level = "INFO"
|
||||||
# https://pycqa.github.io/isort/docs/configuration/config_files/#pyprojecttoml-preferred-format
|
# https://pycqa.github.io/isort/docs/configuration/config_files/#pyprojecttoml-preferred-format
|
||||||
atomic=true
|
atomic=true
|
||||||
profile='black'
|
profile='black'
|
||||||
skip_glob=["*/htmlcov/*","*/migrations/*","*/local_test/*"]
|
skip_glob=[".*", "*/htmlcov/*","*/migrations/*","*/local_test/*"]
|
||||||
line_length=100
|
known_first_party=['djfritz', 'djfritz_ynh']
|
||||||
known_first_party=["djfritz","djfritz_project","djfritz_tests"]
|
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-report term-missing
|
|
||||||
--cov-report html
|
|
||||||
--cov-report xml
|
|
||||||
--no-cov-on-fail
|
|
||||||
--showlocals
|
|
||||||
--darker
|
|
||||||
--doctest-modules
|
|
||||||
--failed-first
|
|
||||||
--new-first
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
omit = [".*"]
|
branch = true
|
||||||
|
parallel = true
|
||||||
|
concurrency = ["multiprocessing"]
|
||||||
|
source = ['.']
|
||||||
|
command_line = './dev-cli.py test'
|
||||||
|
disable_warnings = ["couldnt-parse"]
|
||||||
|
|
||||||
|
[tool.coverage.report]
|
||||||
|
omit = ['.*', '*/tests/*']
|
||||||
|
skip_empty = true
|
||||||
|
fail_under = 10
|
||||||
|
show_missing = true
|
||||||
|
exclude_lines = [
|
||||||
|
'if self.debug:',
|
||||||
|
'pragma: no cover',
|
||||||
|
'raise NotImplementedError',
|
||||||
|
'if __name__ == .__main__.:',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
[tool.tox]
|
[tool.tox] # https://tox.wiki/en/latest/config.html#pyproject-toml
|
||||||
# https://tox.readthedocs.io/en/latest/example/basic.html#pyproject-toml-tox-legacy-ini
|
|
||||||
legacy_tox_ini = """
|
legacy_tox_ini = """
|
||||||
[tox]
|
[tox]
|
||||||
isolated_build = True
|
isolated_build = True
|
||||||
envlist = py{37,38,39,310}
|
envlist = py{312,311}
|
||||||
skip_missing_interpreters = True
|
skip_missing_interpreters = True
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
passenv = *
|
passenv = *
|
||||||
whitelist_externals = make
|
skip_install = true
|
||||||
|
commands_pre =
|
||||||
|
pip install -U pip-tools
|
||||||
|
pip-sync requirements.dev.txt
|
||||||
commands =
|
commands =
|
||||||
make pytest
|
{envpython} -m coverage run --context='{envname}'
|
||||||
|
{envpython} -m coverage combine --append
|
||||||
|
{envpython} -m coverage xml
|
||||||
|
{envpython} -m coverage report
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
warn_unused_configs = true
|
||||||
|
ignore_missing_imports = true
|
||||||
|
allow_redefinition = true # https://github.com/python/mypy/issues/7165
|
||||||
|
show_error_codes = true
|
||||||
|
plugins = []
|
||||||
|
exclude = ['.venv', 'tests']
|
||||||
|
|
||||||
|
|
||||||
|
[manageprojects] # https://github.com/jedie/manageprojects
|
||||||
|
initial_revision = "2281f4b"
|
||||||
|
initial_date = 2023-04-02T17:40:58+02:00
|
||||||
|
cookiecutter_template = "https://github.com/jedie/cookiecutter_templates/"
|
||||||
|
cookiecutter_directory = "yunohost_django_package"
|
||||||
|
applied_migrations = [
|
||||||
|
]
|
||||||
|
|
||||||
|
[manageprojects.cookiecutter_context.cookiecutter]
|
||||||
|
project_name = "django-fritzconnection"
|
||||||
|
full_name = "Jens Diemer"
|
||||||
|
github_username = "jedie"
|
||||||
|
author_email = "git@jensdiemer.de"
|
||||||
|
upstream_pkg_name = "djfritz"
|
||||||
|
upstream_url = "https://github.com/jedie/django-fritzconnection"
|
||||||
|
upstream_pkg_app_name = "djfritz"
|
||||||
|
upstream_pkg_project_name = "djfritz_project"
|
||||||
|
ynh_app_pkg_name = "djfritz_ynh"
|
||||||
|
ynh_app_url = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
||||||
|
bug_tracker_url = "https://github.com/jedie/django-fritzconnection/issues"
|
||||||
|
upstream_version = "0.3.0"
|
||||||
|
ynh_version = "+ynh3"
|
||||||
|
package_description = "Web based FritzBox management using Python/Django."
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
_template = "https://github.com/jedie/cookiecutter_templates/"
|
||||||
|
|
1194
requirements.dev.txt
Normal file
1194
requirements.dev.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,36 +1,182 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# COMMON VARIABLES
|
# RETRIEVE ARGUMENTS FROM THE MANIFEST
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
|
# Transfer the main SSO domain to the App:
|
||||||
|
ynh_current_host=$(cat /etc/yunohost/current_host)
|
||||||
|
__YNH_CURRENT_HOST__=${ynh_current_host}
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# ARGUMENTS FROM CONFIG PANEL
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
# 'debug_enabled' -> '__DEBUG_ENABLED__' -> settings.DEBUG
|
||||||
|
debug_enabled="0" # "1" or "0" string
|
||||||
|
|
||||||
|
# 'log_level' -> '__LOG_LEVEL__' -> settings.LOG_LEVEL
|
||||||
|
log_level="WARNING"
|
||||||
|
|
||||||
|
# 'admin_email' -> '__ADMIN_EMAIL__' add in settings.ADMINS
|
||||||
|
admin_email="${admin}@${domain}"
|
||||||
|
|
||||||
|
# 'default_from_email' -> '__DEFAULT_FROM_EMAIL__' -> settings.DEFAULT_FROM_EMAIL
|
||||||
|
default_from_email="${app}@${domain}"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SET CONSTANTS
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
# e.g.: point pip cache to: /home/yunohost.app/$app/.cache/
|
||||||
|
XDG_CACHE_HOME="$data_dir/.cache/"
|
||||||
|
|
||||||
log_path=/var/log/$app
|
log_path=/var/log/$app
|
||||||
log_file="${log_path}/${app}.log"
|
log_file="${log_path}/${app}.log"
|
||||||
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# PERSONAL HELPERS
|
# HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
_venv_install() {
|
|
||||||
ynh_exec_as "$app" python3 -m venv --upgrade "$install_dir/venv"
|
|
||||||
venvpy="$install_dir/venv/bin/python3"
|
|
||||||
|
|
||||||
ynh_exec_as "$app" "$venvpy" -m pip install --upgrade --no-cache-dir pip
|
#==================================================================================
|
||||||
|
# myynh_install_python() Borrowed from:
|
||||||
|
# https://github.com/YunoHost-Apps/homeassistant_ynh/blob/master/scripts/_common.sh
|
||||||
|
# Until we get a newer Python in YunoHost, see:
|
||||||
|
# https://forum.yunohost.org/t/use-newer-python-than-3-9/22568
|
||||||
|
#==================================================================================
|
||||||
|
py_required_major=3.11
|
||||||
|
py_required_version=$(curl -Ls https://www.python.org/ftp/python/ \
|
||||||
|
| grep '>'$py_required_major | cut -d '/' -f 2 \
|
||||||
|
| cut -d '>' -f 2 | sort -rV | head -n 1) #3.11.8
|
||||||
|
|
||||||
ynh_exec_as "$app" "$venvpy" -m pip install setuptools wheel pyyaml
|
myynh_install_python() {
|
||||||
|
# Declare an array to define the options of this helper.
|
||||||
|
local legacy_args=u
|
||||||
|
local -A args_array=( [p]=python= )
|
||||||
|
local python
|
||||||
|
# Manage arguments with getopts
|
||||||
|
ynh_handle_getopts_args "$@"
|
||||||
|
|
||||||
|
# Check python version from APT
|
||||||
|
local py_apt_version=$(python3 --version | cut -d ' ' -f 2)
|
||||||
|
|
||||||
|
# Usefull variables
|
||||||
|
local python_major=${python%.*}
|
||||||
|
|
||||||
|
# Check existing built version of python in /usr/local/bin
|
||||||
|
if [ -e "/usr/local/bin/python$python_major" ]
|
||||||
|
then
|
||||||
|
local py_built_version=$(/usr/local/bin/python$python_major --version \
|
||||||
|
| cut -d ' ' -f 2)
|
||||||
|
else
|
||||||
|
local py_built_version=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compare version
|
||||||
|
if $(dpkg --compare-versions $py_apt_version ge $python)
|
||||||
|
then
|
||||||
|
# APT >= Required
|
||||||
|
ynh_print_info --message="Using provided python3..."
|
||||||
|
|
||||||
|
py_app_version="python3"
|
||||||
|
|
||||||
|
else
|
||||||
|
# Either python already built or to build
|
||||||
|
if $(dpkg --compare-versions $py_built_version ge $python)
|
||||||
|
then
|
||||||
|
# Built >= Required
|
||||||
|
py_app_version="/usr/local/bin/python${py_built_version%.*}"
|
||||||
|
ynh_print_info --message="Using already used python3 built version: $py_app_version"
|
||||||
|
else
|
||||||
|
# APT < Minimal & Actual < Minimal => Build & install Python into /usr/local/bin
|
||||||
|
ynh_print_info --message="Building $python (may take a while)..."
|
||||||
|
|
||||||
|
# Store current direcotry
|
||||||
|
local MY_DIR=$(pwd)
|
||||||
|
|
||||||
|
# Create a temp direcotry
|
||||||
|
tmpdir="$(mktemp --directory)"
|
||||||
|
cd "$tmpdir"
|
||||||
|
|
||||||
|
# Download
|
||||||
|
wget --output-document="Python-$python.tar.xz" \
|
||||||
|
"https://www.python.org/ftp/python/$python/Python-$python.tar.xz" 2>&1
|
||||||
|
|
||||||
|
# Extract
|
||||||
|
tar xf "Python-$python.tar.xz"
|
||||||
|
|
||||||
|
# Install
|
||||||
|
cd "Python-$python"
|
||||||
|
./configure --enable-optimizations
|
||||||
|
ynh_exec_warn_less make -j4
|
||||||
|
ynh_exec_warn_less make altinstall
|
||||||
|
|
||||||
|
# Go back to working directory
|
||||||
|
cd "$MY_DIR"
|
||||||
|
|
||||||
|
# Clean
|
||||||
|
ynh_secure_remove "$tmpdir"
|
||||||
|
|
||||||
|
# Set version
|
||||||
|
py_app_version="/usr/local/bin/python$python_major"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Save python version in settings
|
||||||
|
ynh_app_setting_set --app=$app --key=python --value="$python"
|
||||||
|
|
||||||
|
# Print some version information:
|
||||||
|
ynh_print_info --message="Python version: $($py_app_version -VV)"
|
||||||
|
ynh_print_info --message="Pip version: $($py_app_version -m pip -V)"
|
||||||
|
}
|
||||||
|
#==================================================================================
|
||||||
|
#==================================================================================
|
||||||
|
|
||||||
|
myynh_setup_python_venv() {
|
||||||
|
# Install Python if needed:
|
||||||
|
myynh_install_python --python="$py_required_version"
|
||||||
|
|
||||||
|
# Create a virtualenv with python installed by myynh_install_python():
|
||||||
|
# Skip pip because of: https://github.com/YunoHost/issues/issues/1960
|
||||||
|
ynh_exec_as $app $py_app_version -m venv --clear --upgrade-deps "$data_dir/venv"
|
||||||
|
|
||||||
|
# Print some version information:
|
||||||
|
ynh_print_info --message="venv Python version: $($data_dir/venv/bin/python3 -VV)"
|
||||||
|
ynh_print_info --message="venv Pip version: $($data_dir/venv/bin/python3 -m pip -V)"
|
||||||
|
|
||||||
|
# run source in a 'sub shell'
|
||||||
|
(
|
||||||
|
set +o nounset
|
||||||
|
source "$data_dir/venv/bin/activate"
|
||||||
|
set -o nounset
|
||||||
|
set -x
|
||||||
|
ynh_exec_as $app $data_dir/venv/bin/pip3 install --upgrade pip wheel setuptools
|
||||||
|
ynh_exec_as $app $data_dir/venv/bin/pip3 install --no-deps -r "$data_dir/requirements.txt"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
_build_app() {
|
myynh_setup_log_file() {
|
||||||
ynh_exec_as "$app" "$venvpy" -m ensurepip
|
(
|
||||||
ynh_exec_as "$app" "$venvpy" -m pip install --upgrade wheel pip setuptools
|
set -x
|
||||||
ynh_exec_as "$app" "$venvpy" -m pip install --no-deps -r "$install_dir/app/requirements.txt"
|
|
||||||
|
mkdir -p "$(dirname "$log_file")"
|
||||||
|
touch "$log_file"
|
||||||
|
|
||||||
|
chown -c -R $app:$app "$log_path"
|
||||||
|
chmod -c o-rwx "$log_path"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#=================================================
|
myynh_fix_file_permissions() {
|
||||||
# EXPERIMENTAL HELPERS
|
(
|
||||||
#=================================================
|
set -x
|
||||||
|
|
||||||
#=================================================
|
# /var/www/$app/
|
||||||
# FUTURE OFFICIAL HELPERS
|
chown -c -R "$app:www-data" "$install_dir"
|
||||||
#=================================================
|
chmod -c o-rwx "$install_dir"
|
||||||
|
|
||||||
|
# /home/yunohost.app/$app/
|
||||||
|
chown -c -R "$app:" "$data_dir"
|
||||||
|
chmod -c o-rwx "$data_dir"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC START
|
||||||
#=================================================
|
#=================================================
|
||||||
# IMPORT GENERIC HELPERS
|
# IMPORT GENERIC HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
@ -16,33 +18,38 @@ ynh_print_info --message="Declaring files to be backed up..."
|
||||||
# BACKUP THE APP MAIN DIR
|
# BACKUP THE APP MAIN DIR
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
|
# /var/www/$app/
|
||||||
ynh_backup --src_path="$install_dir"
|
ynh_backup --src_path="$install_dir"
|
||||||
|
|
||||||
|
# /home/yunohost.app/$app/
|
||||||
|
ynh_backup --src_path="$data_dir"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SYSTEM CONFIGURATION
|
# BACKUP THE NGINX CONFIGURATION
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
# Backup the nginx configuration
|
|
||||||
ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||||
|
|
||||||
# Backup the systemd service unit
|
|
||||||
ynh_backup --src_path="/etc/systemd/system/$app.service"
|
|
||||||
|
|
||||||
# Backup the logrotate configuration
|
|
||||||
ynh_backup --src_path="/etc/logrotate.d/$app"
|
|
||||||
|
|
||||||
#=================================================
|
|
||||||
# BACKUP VARIOUS FILES
|
|
||||||
#=================================================
|
|
||||||
|
|
||||||
ynh_backup --src_path="/var/log/$app/"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# BACKUP THE PostgreSQL DATABASE
|
# BACKUP THE PostgreSQL DATABASE
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
ynh_psql_dump_db --database="$db_name" > db.sql
|
ynh_psql_dump_db --database="$db_name" > db.sql
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SPECIFIC BACKUP
|
||||||
|
#=================================================
|
||||||
|
# BACKUP LOGROTATE
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
ynh_backup --src_path="/etc/logrotate.d/$app"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# BACKUP SYSTEMD
|
||||||
|
#=================================================
|
||||||
|
|
||||||
|
ynh_backup --src_path="/etc/systemd/system/$app.service"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC STARTING
|
||||||
#=================================================
|
#=================================================
|
||||||
# IMPORT GENERIC HELPERS
|
# IMPORT GENERIC HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
@ -7,33 +9,38 @@
|
||||||
source _common.sh
|
source _common.sh
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# STANDARD MODIFICATIONS
|
||||||
#=================================================
|
#=================================================
|
||||||
# STOP SYSTEMD SERVICE
|
# STOP SYSTEMD SERVICE
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Stopping systemd service '$app'..."
|
ynh_script_progression --message="Stopping systemd service '$app'..."
|
||||||
|
|
||||||
ynh_systemd_action --service_name="$app" --action="stop"
|
ynh_systemd_action --service_name=$app --action="stop" --log_path="$log_file"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# MODIFY URL IN NGINX CONF
|
# MODIFY URL IN NGINX CONF
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Updating NGINX web server configuration..." --weight=1
|
ynh_script_progression --message="Updating nginx web server configuration..."
|
||||||
|
|
||||||
ynh_change_url_nginx_config
|
ynh_change_url_nginx_config
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SPECIFIC MODIFICATIONS
|
# UPDATE DJANGO SETTINGS
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Modify $app config file..."
|
ynh_script_progression --message="Update $app settings file..." --weight=1
|
||||||
|
|
||||||
ynh_add_config --template="settings.py" --destination="$install_dir/app/settings.py"
|
path=$new_path
|
||||||
|
domain=$new_domain
|
||||||
|
|
||||||
|
ynh_add_config --template="settings.py" --destination="$data_dir/settings.py"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# START SYSTEMD SERVICE
|
# START SYSTEMD SERVICE
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Starting $app's systemd service..." --weight=1
|
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log"
|
ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
|
|
186
scripts/install
186
scripts/install
|
@ -7,99 +7,147 @@
|
||||||
source _common.sh
|
source _common.sh
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
#=================================================
|
# Install parameters are automatically saved as settings
|
||||||
# INITIALIZE AND STORE SETTINGS
|
#
|
||||||
#=================================================
|
# Settings are automatically loaded as bash variables
|
||||||
|
# in every app script context, therefore typically these will exist:
|
||||||
|
# - $domain
|
||||||
|
# - $path
|
||||||
|
# - $language
|
||||||
|
# ... etc
|
||||||
|
#
|
||||||
|
# Resources defined in the manifest are provisioned prior to this script
|
||||||
|
# and corresponding settings are also available, such as:
|
||||||
|
# - $install_dir
|
||||||
|
# - $port
|
||||||
|
# - $db_name
|
||||||
|
# ...
|
||||||
|
|
||||||
admin_email="$(ynh_user_get_info "$admin" mail)"
|
#
|
||||||
ynh_app_setting_set --app="$app" --key=admin_email --value="$admin_email"
|
# $app is the app id (i.e. 'example' for first install,
|
||||||
|
# or 'example__2', '__3', ... for multi-instance installs)
|
||||||
|
#
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SETTINGS
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Storing installation settings..."
|
||||||
|
|
||||||
|
# Logging:
|
||||||
|
log_file="/var/log/$app/$app.log"
|
||||||
|
ynh_app_setting_set --app=$app --key=log_file --value="$log_file"
|
||||||
|
|
||||||
|
# Redis:
|
||||||
redis_db=$(ynh_redis_get_free_db)
|
redis_db=$(ynh_redis_get_free_db)
|
||||||
ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
ynh_app_setting_set --app=$app --key=redis_db --value="$redis_db"
|
||||||
|
|
||||||
#-------------------------------------------------
|
# App settings:
|
||||||
# config_panel.toml settings:
|
ynh_app_setting_set --app=$app --key=default_from_email --value="$default_from_email"
|
||||||
|
ynh_app_setting_set --app=$app --key=admin_email --value="$admin_email"
|
||||||
debug_enabled="0"
|
ynh_app_setting_set --app=$app --key=debug_enabled --value="$debug_enabled"
|
||||||
ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled"
|
ynh_app_setting_set --app=$app --key=log_level --value="$log_level"
|
||||||
log_level="WARNING"
|
|
||||||
ynh_app_setting_set --app="$app" --key=log_level --value="$log_level"
|
|
||||||
default_from_email="${app}@${domain}"
|
|
||||||
ynh_app_setting_set --app="$app" --key=default_from_email --value="$default_from_email"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# DOWNLOAD, CHECK AND UNPACK SOURCE
|
# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Setting up source files..." --weight=1
|
ynh_script_progression --message="Validating installation parameters..."
|
||||||
|
|
||||||
mkdir -p "$install_dir/"{app,public/media,public/static}
|
mkdir -p "$install_dir/media" "$install_dir/static"
|
||||||
|
|
||||||
ynh_add_config --template="requirements.txt" --destination="$install_dir/app/requirements.txt"
|
#=================================================
|
||||||
|
# SETUP LOG FILE
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Setup logging..."
|
||||||
|
|
||||||
ynh_add_config --template="gunicorn.conf.py" --destination="$install_dir/app/gunicorn.conf.py"
|
myynh_setup_log_file
|
||||||
|
|
||||||
ynh_add_config --template="manage.py" --destination="$install_dir/app/manage.py"
|
# Use logrotate to manage application logfile(s)
|
||||||
chmod +x "$install_dir/app/manage.py"
|
ynh_use_logrotate --logfile="$log_file" --specific_user=$app
|
||||||
|
|
||||||
ynh_add_config --template="settings.py" --destination="$install_dir/app/settings.py"
|
|
||||||
ynh_add_config --template="setup_user.py" --destination="$install_dir/app/setup_user.py"
|
|
||||||
ynh_add_config --template="urls.py" --destination="$install_dir/app/urls.py"
|
|
||||||
ynh_add_config --template="wsgi.py" --destination="$install_dir/app/wsgi.py"
|
|
||||||
|
|
||||||
touch "$install_dir/app/local_settings.py"
|
|
||||||
|
|
||||||
chown -R "$app:www-data" "$install_dir"
|
|
||||||
|
|
||||||
mkdir -p "/var/log/$app"
|
|
||||||
touch "/var/log/$app/$app.log"
|
|
||||||
chown -R "$app:$app" "/var/log/$app"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# PYTHON VIRTUALENV
|
# PYTHON VIRTUALENV
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Installing $app..." --weight=10
|
ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45
|
||||||
|
cp ../conf/requirements.txt "$data_dir/requirements.txt"
|
||||||
_venv_install
|
myynh_setup_python_venv
|
||||||
|
|
||||||
_build_app
|
|
||||||
|
|
||||||
pushd "$install_dir/app"
|
|
||||||
# Just for debugging:
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py diffsettings
|
|
||||||
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py migrate --no-input
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py collectstatic --no-input
|
|
||||||
|
|
||||||
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py create_superuser --username="$admin" --email="$(ynh_user_get_info "$admin" mail)"
|
|
||||||
|
|
||||||
# Check the configuration
|
|
||||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py check --deploy || true
|
|
||||||
popd
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# SYSTEM CONFIGURATION
|
# copy config files
|
||||||
#=================================================
|
# ================================================
|
||||||
ynh_script_progression --message="Adding system configurations related to $app..." --weight=1
|
ynh_script_progression --message="Create $app configuration files..."
|
||||||
|
|
||||||
# Create a dedicated NGINX config using the conf/nginx.conf template
|
ynh_add_config --template="gunicorn.conf.py" --destination="$data_dir/gunicorn.conf.py"
|
||||||
ynh_add_nginx_config
|
|
||||||
|
|
||||||
# Create a dedicated systemd config
|
ynh_add_config --template="manage.py" --destination="$data_dir/manage.py"
|
||||||
ynh_add_systemd_config
|
chmod -c +x "$data_dir/manage.py"
|
||||||
yunohost service add "$app" --description="Django-fritzconnection server" --log="/var/log/$app/$app.log"
|
|
||||||
|
|
||||||
# Use logrotate to manage app-specific logfile(s)
|
ynh_add_config --template="settings.py" --destination="$data_dir/settings.py"
|
||||||
ynh_use_logrotate "$log_file"
|
ynh_add_config --template="setup_user.py" --destination="$data_dir/setup_user.py"
|
||||||
|
ynh_add_config --template="urls.py" --destination="$data_dir/urls.py"
|
||||||
|
ynh_add_config --template="wsgi.py" --destination="$data_dir/wsgi.py"
|
||||||
|
|
||||||
|
touch "$data_dir/local_settings.py"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# START SYSTEMD SERVICE
|
# MIGRATE / COLLECTSTATIC / CREATEADMIN
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Starting $app's systemd service..." --weight=1
|
ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight=10
|
||||||
|
|
||||||
# Start a systemd service
|
cd "$data_dir" || exit
|
||||||
ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log"
|
|
||||||
|
# Just for debugging:
|
||||||
|
./manage.py diffsettings
|
||||||
|
|
||||||
|
./manage.py migrate --no-input
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
|
||||||
|
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||||
|
./manage.py create_superuser --username="$admin" --email="$(ynh_user_get_info "$admin" mail)"
|
||||||
|
|
||||||
|
# Check the configuration
|
||||||
|
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||||
|
./manage.py check --deploy || true
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# INTEGRATE SERVICE IN YUNOHOST
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||||
|
|
||||||
|
yunohost service add --description $app $app
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC FINALIZATION
|
||||||
|
#=================================================
|
||||||
|
# SECURE FILES AND DIRECTORIES
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Set file permissions..."
|
||||||
|
myynh_fix_file_permissions
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SETUP SYSTEMD
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
|
# https://yunohost.org/en/packaging_apps_helpers#ynh-add-systemd-config
|
||||||
|
# https://github.com/YunoHost/yunohost/blob/dev/helpers/systemd
|
||||||
|
ynh_add_systemd_config --service=$app --template="systemd.service"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# Start the app server via systemd
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
|
ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# NGINX CONFIGURATION
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Configuring nginx web server..."
|
||||||
|
|
||||||
|
# Create a dedicated nginx config
|
||||||
|
# https://yunohost.org/en/contribute/packaging_apps/helpers
|
||||||
|
# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx
|
||||||
|
ynh_add_nginx_config "public_path" "port"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC START
|
||||||
#=================================================
|
#=================================================
|
||||||
# IMPORT GENERIC HELPERS
|
# IMPORT GENERIC HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
@ -8,19 +10,56 @@ source _common.sh
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# REMOVE SYSTEM CONFIGURATIONS
|
# STANDARD REMOVE
|
||||||
|
#=================================================
|
||||||
|
# REMOVE SERVICE FROM ADMIN PANEL
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Removing system configurations related to $app..." --weight=1
|
|
||||||
|
|
||||||
# Remove the service from the list of services known by YunoHost (added from `yunohost service add`)
|
# Remove a service from the admin panel, added by `yunohost service add`
|
||||||
if ynh_exec_warn_less yunohost service status "$app" >/dev/null; then
|
if yunohost service status $app >/dev/null 2>&1
|
||||||
yunohost service remove "$app"
|
then
|
||||||
|
ynh_script_progression --message="Removing $app service integration..."
|
||||||
|
yunohost service remove $app
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ynh_remove_systemd_config
|
#=================================================
|
||||||
|
# STOP PYINVENTORY'S SERVICES
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Stopping and removing systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
|
ynh_remove_systemd_config --service=$app
|
||||||
|
|
||||||
|
##=================================================
|
||||||
|
## REMOVE REDIS DB
|
||||||
|
##=================================================
|
||||||
|
|
||||||
|
ynh_redis_remove_db
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# REMOVE APP MAIN DIR
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Removing app main directory..."
|
||||||
|
|
||||||
|
# /var/www/$app/
|
||||||
|
ynh_secure_remove --file="$install_dir"
|
||||||
|
|
||||||
|
# /home/yunohost.app/$app/
|
||||||
|
ynh_secure_remove --file="$data_dir"
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# REMOVE NGINX CONFIGURATION
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Removing nginx web server configuration..."
|
||||||
|
|
||||||
|
# Remove the dedicated nginx config
|
||||||
ynh_remove_nginx_config
|
ynh_remove_nginx_config
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# REMOVE LOGROTATE CONFIGURATION
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Removing logrotate configuration..."
|
||||||
|
|
||||||
|
# Remove the app-specific logrotate config
|
||||||
ynh_remove_logrotate
|
ynh_remove_logrotate
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
109
scripts/restore
109
scripts/restore
|
@ -1,5 +1,7 @@
|
||||||
j#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC START
|
||||||
#=================================================
|
#=================================================
|
||||||
# IMPORT GENERIC HELPERS
|
# IMPORT GENERIC HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
@ -8,61 +10,86 @@ source ../settings/scripts/_common.sh
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# RESTORE THE APP MAIN DIR
|
# STANDARD RESTORATION STEPS
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Restoring the app main directory..."
|
# RESTORE THE NGINX CONFIGURATION
|
||||||
|
|
||||||
ynh_restore_file --origin_path="$install_dir"
|
|
||||||
|
|
||||||
chmod -R o-rwx "$install_dir"
|
|
||||||
chown -R "$app:www-data" "$install_dir"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# RESTORE THE POSTGRESQL DATABASE
|
ynh_script_progression --message="Restoring the NGINX web server configuration..." --weight=1
|
||||||
#=================================================
|
|
||||||
ynh_script_progression --message="Restoring the PostgreSQL database..." --weight=1
|
|
||||||
|
|
||||||
ynh_psql_connect_as --user="$db_user" --password="$db_pwd" --database="$db_name" < ./db.sql
|
|
||||||
|
|
||||||
#=================================================
|
|
||||||
# PYTHON VIRTUALENV
|
|
||||||
# Maybe the backup contains another Python version
|
|
||||||
#=================================================
|
|
||||||
ynh_script_progression --message="Updating Python virtualenv and rebuilding $app..." --weight=5
|
|
||||||
|
|
||||||
# Always recreate everything fresh with current python version
|
|
||||||
ynh_secure_remove "$install_dir/venv"
|
|
||||||
_venv_install
|
|
||||||
chown -R "$app:www-data" "$install_dir"
|
|
||||||
_build_app
|
|
||||||
|
|
||||||
#=================================================
|
|
||||||
# RESTORE SYSTEM CONFIGURATIONS
|
|
||||||
#=================================================
|
|
||||||
ynh_script_progression --message="Restoring system configurations related to $app..." --weight=1
|
|
||||||
|
|
||||||
ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||||
|
|
||||||
ynh_restore_file --origin_path="/etc/systemd/system/$app.service"
|
#=================================================
|
||||||
systemctl enable "$app.service" --quiet
|
# RESTORE THE APP MAIN DIR
|
||||||
yunohost service add "$app" --description="Django-fritzconnection server" --log="/var/log/$app/$app.log"
|
#=================================================
|
||||||
|
ynh_script_progression --message="Restoring $app main directory..."
|
||||||
|
|
||||||
|
ynh_restore_file --origin_path="$install_dir"
|
||||||
|
ynh_restore_file --origin_path="$data_dir"
|
||||||
|
|
||||||
|
ynh_script_progression --message="Set file permissions..."
|
||||||
|
myynh_fix_file_permissions
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# PYTHON VIRTUALENV
|
||||||
|
# Maybe the backup contains a other Python version
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45
|
||||||
|
|
||||||
|
myynh_setup_python_venv
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# RESTORE THE PostgreSQL DATABASE
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Restoring the PostgreSQL database..." --weight=5
|
||||||
|
|
||||||
|
ynh_psql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# RESTORE SYSTEMD
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Restoring the systemd $app configuration..."
|
||||||
|
|
||||||
|
ynh_restore_file --origin_path="/etc/systemd/system/$app.service"
|
||||||
|
systemctl enable $app.service --quiet
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# INTEGRATE SERVICE IN YUNOHOST
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||||
|
|
||||||
|
yunohost service add --description $app $app
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# RESTORE THE LOGROTATE CONFIGURATION
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Setup logging..."
|
||||||
|
|
||||||
|
myynh_setup_log_file
|
||||||
ynh_restore_file --origin_path="/etc/logrotate.d/$app"
|
ynh_restore_file --origin_path="/etc/logrotate.d/$app"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# RESTORE VARIOUS FILES
|
# GENERIC FINALIZATION
|
||||||
#=================================================
|
#=================================================
|
||||||
|
# SECURE FILES AND DIRECTORIES
|
||||||
ynh_restore_file --origin_path="/var/log/$app/"
|
#=================================================
|
||||||
|
ynh_script_progression --message="Set file permissions..."
|
||||||
|
myynh_fix_file_permissions
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# RELOAD NGINX AND PHP-FPM OR THE APP SERVICE
|
# GENERIC FINALIZATION
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Reloading NGINX web server and $app's service..." --weight=1
|
# START PYINVENTORY
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log"
|
ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file"
|
||||||
|
|
||||||
ynh_systemd_action --service_name=nginx --action=reload
|
#=================================================
|
||||||
|
# RELOAD NGINX
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Reloading nginx web server..."
|
||||||
|
|
||||||
|
ynh_systemd_action --service_name="nginx" --action="reload"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
|
|
172
scripts/upgrade
172
scripts/upgrade
|
@ -7,114 +7,112 @@
|
||||||
source _common.sh
|
source _common.sh
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
# config_panel.toml settings:
|
||||||
|
|
||||||
|
if [ -z "$debug_enabled" ]; then
|
||||||
|
debug_enabled="0"
|
||||||
|
ynh_app_setting_set --app=$app --key=debug_enabled --value="$debug_enabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$log_level" ]; then
|
||||||
|
log_level="WARNING"
|
||||||
|
ynh_app_setting_set --app=$app --key=log_level --value="$log_level"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$admin_email" ]; then
|
||||||
|
admin_email="${admin}@${domain}"
|
||||||
|
ynh_app_setting_set --app=$app --key=admin_email --value="$admin_email"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$default_from_email" ]; then
|
||||||
|
default_from_email="${app}@${domain}"
|
||||||
|
ynh_app_setting_set --app=$app --key=default_from_email --value="$default_from_email"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# STANDARD UPGRADE STEPS
|
||||||
#=================================================
|
#=================================================
|
||||||
# STOP SYSTEMD SERVICE
|
# STOP SYSTEMD SERVICE
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Stopping $app's systemd service..." --weight=1
|
ynh_script_progression --message="Stopping systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
|
ynh_systemd_action --service_name=$app --action="stop" --log_path="$log_file"
|
||||||
|
|
||||||
ynh_systemd_action --service_name="$app" --action="stop" --log_path="/var/log/$app/$app.log"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# ENSURE DOWNWARD COMPATIBILITY
|
# SETUP SYSTEMD
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Ensuring downward compatibility..." --weight=1
|
ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
if [ -z "${debug_enabled:-}" ]; then
|
ynh_add_systemd_config --service=$app --template="systemd.service"
|
||||||
debug_enabled="0"
|
|
||||||
ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${log_level:-}" ]; then
|
|
||||||
log_level="WARNING"
|
|
||||||
ynh_app_setting_set --app="$app" --key=log_level --value="$log_level"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${admin_email:-}" ]; then
|
|
||||||
admin_email="${admin}@${domain}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${default_from_email:-}" ]; then
|
|
||||||
default_from_email="${app}@${domain}"
|
|
||||||
ynh_app_setting_set --app="$app" --key=default_from_email --value="$default_from_email"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "/opt/yunohost/$app" ]; then
|
|
||||||
if [ -d "$install_dir/app" ]; then
|
|
||||||
ynh_secure_remove --file="/opt/yunohost/$app"
|
|
||||||
else
|
|
||||||
mv "/opt/yunohost/$app" "$install_dir/app"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
#=================================================
|
|
||||||
# DOWNLOAD, CHECK AND UNPACK SOURCE
|
|
||||||
#=================================================
|
|
||||||
ynh_script_progression --message="Upgrading source files..." --weight=1
|
|
||||||
|
|
||||||
mkdir -p "$install_dir/"{app,public/media,public/static}
|
|
||||||
|
|
||||||
ynh_add_config --template="requirements.txt" --destination="$install_dir/app/requirements.txt"
|
|
||||||
|
|
||||||
ynh_add_config --template="gunicorn.conf.py" --destination="$install_dir/app/gunicorn.conf.py"
|
|
||||||
|
|
||||||
ynh_add_config --template="manage.py" --destination="$install_dir/app/manage.py"
|
|
||||||
chmod +x "$install_dir/app/manage.py"
|
|
||||||
|
|
||||||
ynh_add_config --template="settings.py" --destination="$install_dir/app/settings.py"
|
|
||||||
ynh_add_config --template="setup_user.py" --destination="$install_dir/app/setup_user.py"
|
|
||||||
ynh_add_config --template="urls.py" --destination="$install_dir/app/urls.py"
|
|
||||||
ynh_add_config --template="wsgi.py" --destination="$install_dir/app/wsgi.py"
|
|
||||||
|
|
||||||
chown -R "$app:www-data" "$install_dir"
|
|
||||||
|
|
||||||
chown -R "$app:www-data" "$install_dir"
|
|
||||||
|
|
||||||
mkdir -p "/var/log/$app"
|
|
||||||
touch "/var/log/$app/$app.log"
|
|
||||||
chown -R "$app:$app" "/var/log/$app"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# PYTHON VIRTUALENV
|
# PYTHON VIRTUALENV
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Upgrading $app..." --weight=10
|
ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45
|
||||||
|
cp ../conf/requirements.txt "$data_dir/requirements.txt"
|
||||||
_venv_install
|
myynh_setup_python_venv
|
||||||
|
|
||||||
_build_app
|
|
||||||
|
|
||||||
pushd "$install_dir/app"
|
|
||||||
# Just for debugging:
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py diffsettings
|
|
||||||
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py migrate --no-input
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py collectstatic --no-input
|
|
||||||
|
|
||||||
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py create_superuser --username="$admin" --email="$(ynh_user_get_info "$admin" mail)"
|
|
||||||
|
|
||||||
# Check the configuration
|
|
||||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
|
||||||
ynh_exec_as "$app" "$venvpy" ./manage.py check --deploy || true
|
|
||||||
popd
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# REAPPLY SYSTEM CONFIGURATIONS
|
# copy config files
|
||||||
#=================================================
|
# ================================================
|
||||||
ynh_script_progression --message="Upgrading system configurations related to $app..." --weight=1
|
ynh_script_progression --message="Create project configuration files..."
|
||||||
|
|
||||||
ynh_add_nginx_config
|
ynh_add_config --template="gunicorn.conf.py" --destination="$data_dir/gunicorn.conf.py"
|
||||||
|
|
||||||
ynh_add_systemd_config
|
ynh_add_config --template="manage.py" --destination="$data_dir/manage.py"
|
||||||
yunohost service add "$app" --description="Django-fritzconnection server" --log="/var/log/$app/$app.log"
|
chmod -c +x "$data_dir/manage.py"
|
||||||
|
|
||||||
ynh_use_logrotate --non-append
|
ynh_add_config --template="settings.py" --destination="$data_dir/settings.py"
|
||||||
|
ynh_add_config --template="setup_user.py" --destination="$data_dir/setup_user.py"
|
||||||
|
ynh_add_config --template="urls.py" --destination="$data_dir/urls.py"
|
||||||
|
ynh_add_config --template="wsgi.py" --destination="$data_dir/wsgi.py"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# START SYSTEMD SERVICE
|
# MIGRATE PYINVENTORY
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Starting $app's systemd service..." --weight=1
|
ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight=10
|
||||||
|
|
||||||
ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log"
|
cd "$data_dir" || exit
|
||||||
|
|
||||||
|
# Just for debugging:
|
||||||
|
./manage.py diffsettings
|
||||||
|
|
||||||
|
./manage.py migrate --no-input
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
|
||||||
|
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||||
|
./manage.py create_superuser --username="$admin" --email="$(ynh_user_get_info "$admin" mail)"
|
||||||
|
|
||||||
|
# Check the configuration
|
||||||
|
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||||
|
./manage.py check --deploy || true
|
||||||
|
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# SETUP LOGROTATE
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Upgrading logrotate configuration..."
|
||||||
|
|
||||||
|
# Use logrotate to manage app-specific logfile(s)
|
||||||
|
ynh_use_logrotate --logfile="$log_file" --specific_user=$app --non-append
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# GENERIC FINALIZATION
|
||||||
|
#=================================================
|
||||||
|
# SECURE FILES AND DIRECTORIES
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Set file permissions..."
|
||||||
|
myynh_fix_file_permissions
|
||||||
|
|
||||||
|
#=================================================
|
||||||
|
# Start the app server via systemd
|
||||||
|
#=================================================
|
||||||
|
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||||
|
|
||||||
|
yunohost service add --description $app $app
|
||||||
|
ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
|
|
26
tests.toml
26
tests.toml
|
@ -1,5 +1,3 @@
|
||||||
#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json
|
|
||||||
|
|
||||||
test_format = 1.0
|
test_format = 1.0
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
|
@ -8,4 +6,26 @@ test_format = 1.0
|
||||||
# Tests to run
|
# Tests to run
|
||||||
# ------------
|
# ------------
|
||||||
|
|
||||||
test_upgrade_from.4b0799f31dfbde3884f88aed8ebb5a42c4dc4a69.name = "Packaging v1"
|
# NB: the tests to run are automatically deduced by the CI script according to the
|
||||||
|
# content of the app's manifest. The declarations below allow to customize which
|
||||||
|
# tests are ran, possibly add special test suite to test special args, or
|
||||||
|
# declare which commits to test upgrade from.
|
||||||
|
#
|
||||||
|
# You can also decide (though this is discouraged!) to ban/ignore some tests,
|
||||||
|
|
||||||
|
# The test IDs to be used in only/exclude statements are:
|
||||||
|
# install.root, install.subdir, install.nourl, install.multi, backup_restore, upgrade, upgrade.someCommitId change_url
|
||||||
|
#exclude = ["install.private", "install.multi"]
|
||||||
|
|
||||||
|
# -------------------------------
|
||||||
|
# Default args to use for install
|
||||||
|
# -------------------------------
|
||||||
|
|
||||||
|
# By default, the CI will automagically fill the 'standard' args
|
||||||
|
# such as domain, path, admin, is_public and password with relevant values
|
||||||
|
# and also install args with a "default" provided in the manifest..
|
||||||
|
# It should only make sense to declare custom args here for args with no default values
|
||||||
|
|
||||||
|
args.default_from_email = "default_from_email@example.tld"
|
||||||
|
args.admin_email = "admin_email@example.tld"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue