mirror of
https://github.com/YunoHost-Apps/pyinventory_ynh.git
synced 2024-09-03 20:16:09 +02:00
commit
7bf009e0df
36 changed files with 1231 additions and 691 deletions
|
@ -10,7 +10,7 @@ trim_trailing_whitespace = true
|
|||
insert_final_newline = true
|
||||
|
||||
[*.py]
|
||||
line_length = 119
|
||||
max_line_length = 120
|
||||
|
||||
[{Makefile,**.mk}]
|
||||
indent_style = tab
|
||||
|
@ -18,4 +18,3 @@ insert_final_newline = false
|
|||
|
||||
[*.yml]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
|
20
.github/workflows/pytest.yml
vendored
20
.github/workflows/pytest.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
strategy:
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
python-version: [3.9, 3.8, 3.7]
|
||||
python-version: ["3.10", "3.9", "3.8", "3.7"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
@ -23,13 +23,18 @@ jobs:
|
|||
run: |
|
||||
git fetch origin master
|
||||
- name: 'Set up Python ${{ matrix.python-version }}'
|
||||
uses: actions/setup-python@v1
|
||||
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-poetry
|
||||
make install
|
||||
|
||||
- name: 'List installed packages'
|
||||
|
@ -40,13 +45,12 @@ jobs:
|
|||
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
|
||||
|
||||
- name: 'Run linters'
|
||||
if: matrix.python-version == '3.8'
|
||||
run: |
|
||||
make lint
|
||||
|
|
7
Makefile
7
Makefile
|
@ -18,13 +18,12 @@ check-poetry:
|
|||
|
||||
install-poetry: ## install or update poetry
|
||||
pip3 install -U pip
|
||||
pip3 install -U poetry
|
||||
pip3 install -U "poetry<1.2" # https://forum.yunohost.org/t/invalid-pep-440-version-0-16-0-ynh1/21293
|
||||
|
||||
install: check-poetry ## install project via poetry
|
||||
poetry install
|
||||
|
||||
update: install-poetry ## update the sources and installation and generate "conf/requirements.txt"
|
||||
poetry run pip install -U pip
|
||||
poetry update
|
||||
poetry export -f requirements.txt --output conf/requirements.txt
|
||||
|
||||
|
@ -45,7 +44,7 @@ tox: check-poetry ## Run pytest via tox with all environments
|
|||
poetry run tox
|
||||
|
||||
pytest: install ## Run pytest
|
||||
poetry run python3 ./run_pytest.py
|
||||
poetry run pytest
|
||||
|
||||
local-test: install ## Run local_test.py to run the project locally
|
||||
poetry run python3 ./local_test.py
|
||||
|
@ -53,6 +52,8 @@ local-test: install ## Run local_test.py to run the project locally
|
|||
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
|
||||
|
||||
##############################################################################
|
||||
|
||||
|
|
77
README.md
77
README.md
|
@ -1,45 +1,49 @@
|
|||
<!--
|
||||
N.B.: This README was automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator
|
||||
It shall NOT be edited by hand.
|
||||
-->
|
||||
|
||||
# PyInventory for YunoHost
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory) [](https://ci-apps.yunohost.org/ci/apps/pyinventory/) [](https://dash.yunohost.org/appci/app/pyinventory)
|
||||
|
||||
[](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml) [](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml) [](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh)
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory)  
|
||||
[](https://install-app.yunohost.org/?app=pyinventory)
|
||||
|
||||
*[Lire ce readme en français.](./README_fr.md)*
|
||||
|
||||
> *This package allows you to install PyInventory quickly and simply on a YunoHost server.
|
||||
If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.*
|
||||
|
||||
Pull requests welcome ;)
|
||||
|
||||
## Overview
|
||||
|
||||
[PyInventory](https://github.com/jedie/PyInventory) is a libre web-based management to catalog things including state and location etc. using [Python](https://www.python.org/)/[Django](https://www.djangoproject.com/).
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory) [](https://ci-apps.yunohost.org/ci/apps/pyinventory/) [](https://dash.yunohost.org/appci/app/pyinventory)
|
||||
|
||||
[](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml) [](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml) [](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Pull requests welcome ;)
|
||||
|
||||
This package for YunoHost used [django-yunohost-integration](https://github.com/YunoHost-Apps/django_yunohost_integration)
|
||||
|
||||
More screenshots are here: jedie.github.io/tree/master/screenshots/PyInventory
|
||||
|
||||
|
||||
**Shipped version:** 0.16.0~ynh1
|
||||
|
||||
|
||||
## Screenshots
|
||||
|
||||
More screenshots are here: [jedie.github.io/tree/master/screenshots/PyInventory](https://github.com/jedie/jedie.github.io/blob/master/screenshots/PyInventory/README.creole)
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||
More screenshots are here: [jedie.github.io/tree/master/screenshots/PyInventory](https://github.com/jedie/jedie.github.io/blob/master/screenshots/PyInventory/README.creole)
|
||||
## Disclaimers / important information
|
||||
|
||||
## Settings and upgrades
|
||||
|
||||
|
@ -193,3 +197,24 @@ Notes:
|
|||
* SQlite database will be used
|
||||
* A super user with username `test` and password `test` is created
|
||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
||||
|
||||
## Documentation and resources
|
||||
|
||||
* Official app website: <https://github.com/jedie/PyInventory>
|
||||
* Upstream app code repository: <https://github.com/jedie/PyInventory>
|
||||
* YunoHost documentation for this app: <https://yunohost.org/app_pyinventory>
|
||||
* Report a bug: <https://github.com/YunoHost-Apps/pyinventory_ynh/issues>
|
||||
|
||||
## Developer info
|
||||
|
||||
Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing).
|
||||
|
||||
To try the testing branch, please proceed like that.
|
||||
|
||||
``` bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
or
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
**More info regarding app packaging:** <https://yunohost.org/packaging_apps>
|
||||
|
|
220
README_fr.md
Normal file
220
README_fr.md
Normal file
|
@ -0,0 +1,220 @@
|
|||
<!--
|
||||
N.B.: This README was automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator
|
||||
It shall NOT be edited by hand.
|
||||
-->
|
||||
|
||||
# PyInventory pour YunoHost
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory)  
|
||||
[](https://install-app.yunohost.org/?app=pyinventory)
|
||||
|
||||
*[Read this readme in english.](./README.md)*
|
||||
|
||||
> *Ce package vous permet d'installer PyInventory rapidement et simplement sur un serveur YunoHost.
|
||||
Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.*
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
[PyInventory](https://github.com/jedie/PyInventory) is a libre web-based management to catalog things including state and location etc. using [Python](https://www.python.org/)/[Django](https://www.djangoproject.com/).
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory) [](https://ci-apps.yunohost.org/ci/apps/pyinventory/) [](https://dash.yunohost.org/appci/app/pyinventory)
|
||||
|
||||
[](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml) [](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml) [](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Pull requests welcome ;)
|
||||
|
||||
This package for YunoHost used [django-yunohost-integration](https://github.com/YunoHost-Apps/django_yunohost_integration)
|
||||
|
||||
More screenshots are here: jedie.github.io/tree/master/screenshots/PyInventory
|
||||
|
||||
|
||||
**Version incluse :** 0.16.0~ynh1
|
||||
|
||||
|
||||
## Captures d'écran
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## Avertissements / informations importantes
|
||||
|
||||
## Settings and upgrades
|
||||
|
||||
Almost everything related to PyInventory's configuration is handled in a `"../conf/settings.py"` file.
|
||||
You can edit the file `/opt/yunohost/pyinventory/local_settings.py` to enable or disable features.
|
||||
|
||||
Test sending emails:
|
||||
|
||||
```bash
|
||||
ssh admin@yourdomain.tld
|
||||
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
||||
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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.
|
||||
To check current ADMINS run:
|
||||
|
||||
```bash
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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'),)" >> /opt/yunohost/pyinventory/local_settings.py
|
||||
```
|
||||
|
||||
To check the effective settings, run this:
|
||||
```bash
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
* Report a bug about this package: https://github.com/YunoHost-Apps/pyinventory_ynh
|
||||
* Report a bug about PyInventory itself: https://github.com/jedie/PyInventory
|
||||
* YunoHost website: https://yunohost.org/
|
||||
|
||||
---
|
||||
|
||||
# Developer info
|
||||
|
||||
## package installation / debugging
|
||||
|
||||
Please send your pull request to https://github.com/YunoHost-Apps/pyinventory_ynh
|
||||
|
||||
Try 'main' branch, e.g.:
|
||||
```bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug
|
||||
or
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug
|
||||
```
|
||||
|
||||
Try 'testing' branch, e.g.:
|
||||
```bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
or
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
To remove call e.g.:
|
||||
```bash
|
||||
sudo yunohost app remove pyinventory
|
||||
```
|
||||
|
||||
Backup / remove / restore cycle, e.g.:
|
||||
```bash
|
||||
yunohost backup create --apps pyinventory
|
||||
yunohost backup list
|
||||
archives:
|
||||
- pyinventory-pre-upgrade1
|
||||
- 20201223-163434
|
||||
yunohost app remove pyinventory
|
||||
yunohost backup restore 20201223-163434 --apps pyinventory
|
||||
```
|
||||
|
||||
Debug installation, e.g.:
|
||||
```bash
|
||||
root@yunohost:~# ls -la /var/www/pyinventory/
|
||||
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 /opt/yunohost/pyinventory/
|
||||
total 58
|
||||
drwxr-xr-x 5 pyinventory pyinventory 11 Dec 8 08:39 .
|
||||
drwxr-xr-x 3 root root 3 Dec 8 08:36 ..
|
||||
-rw-r--r-- 1 pyinventory pyinventory 460 Dec 8 08:39 gunicorn.conf.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 0 Dec 8 08:39 local_settings.py
|
||||
-rwxr-xr-x 1 pyinventory pyinventory 274 Dec 8 08:39 manage.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 171 Dec 8 08:39 secret.txt
|
||||
drwxr-xr-x 6 pyinventory pyinventory 6 Dec 8 08:37 venv
|
||||
-rw-r--r-- 1 pyinventory pyinventory 115 Dec 8 08:39 wsgi.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 4737 Dec 8 08:39 settings.py
|
||||
|
||||
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
||||
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py check
|
||||
PyInventory v0.8.2 (Django v2.2.17)
|
||||
DJANGO_SETTINGS_MODULE='settings'
|
||||
PROJECT_PATH:/opt/yunohost/pyinventory/venv/lib/python3.7/site-packages
|
||||
BASE_PATH:/opt/yunohost/pyinventory
|
||||
System check identified no issues (0 silenced).
|
||||
|
||||
root@yunohost:~# tail -f /var/log/pyinventory/pyinventory.log
|
||||
root@yunohost:~# cat /etc/systemd/system/pyinventory.service
|
||||
|
||||
root@yunohost:~# systemctl reload-or-restart pyinventory
|
||||
root@yunohost:~# journalctl --unit=pyinventory --follow
|
||||
```
|
||||
|
||||
## local test
|
||||
|
||||
For quicker developing of PyInventory in the context of YunoHost app,
|
||||
it's possible to run the Django developer server with the settings
|
||||
and urls made for YunoHost installation.
|
||||
|
||||
e.g.:
|
||||
```bash
|
||||
~$ git clone https://github.com/YunoHost-Apps/pyinventory_ynh.git
|
||||
~$ cd pyinventory_ynh/
|
||||
~/pyinventory_ynh$ make
|
||||
install-poetry install or update poetry
|
||||
install install PyInventory via poetry
|
||||
update update the sources and installation
|
||||
local-test Run local_test.py to run pyinventory_ynh locally
|
||||
~/pyinventory_ynh$ make install-poetry
|
||||
~/pyinventory_ynh$ make install
|
||||
~/pyinventory_ynh$ make local-test
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* SQlite database will be used
|
||||
* A super user with username `test` and password `test` is created
|
||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
||||
|
||||
## Documentations et ressources
|
||||
|
||||
* Site officiel de l'app : <https://github.com/jedie/PyInventory>
|
||||
* Dépôt de code officiel de l'app : <https://github.com/jedie/PyInventory>
|
||||
* Documentation YunoHost pour cette app : <https://yunohost.org/app_pyinventory>
|
||||
* Signaler un bug : <https://github.com/YunoHost-Apps/pyinventory_ynh/issues>
|
||||
|
||||
## Informations pour les développeurs
|
||||
|
||||
Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing).
|
||||
|
||||
Pour essayer la branche testing, procédez comme suit.
|
||||
|
||||
``` bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
ou
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
**Plus d'infos sur le packaging d'applications :** <https://yunohost.org/packaging_apps>
|
|
@ -16,7 +16,7 @@
|
|||
setup_sub_dir=1
|
||||
setup_root=1
|
||||
setup_nourl=0
|
||||
setup_private=1
|
||||
setup_private=0
|
||||
setup_public=1
|
||||
upgrade=1
|
||||
backup_restore=1
|
||||
|
|
|
@ -17,4 +17,4 @@ accesslog = '__LOG_FILE__'
|
|||
errorlog = '__LOG_FILE__'
|
||||
|
||||
# https://docs.gunicorn.org/en/latest/settings.html#pidfile
|
||||
pidfile = '__FINAL_HOME_PATH__/gunicorn.pid'
|
||||
pidfile = '__FINALPATH__/gunicorn.pid'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!__FINAL_HOME_PATH__/venv/bin/python
|
||||
#!__FINALPATH__/venv/bin/python
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
|
||||
location __PATH__/static/ {
|
||||
# Django static files
|
||||
# Service static files by nginx
|
||||
# e.g.: /var/www/$app/static
|
||||
alias __PUBLIC_PATH__/static/;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
# TODO: django-sendfile2:
|
||||
#location __PATH__/media/ {
|
||||
# # DATA_DIR/media/
|
||||
# alias __PUBLIC_PATH__/media/;
|
||||
# expires 30d;
|
||||
#}
|
||||
|
||||
location __PATH__/ {
|
||||
# https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf
|
||||
|
||||
|
|
|
@ -7,24 +7,24 @@ async-timeout==4.0.2; python_version >= "3.7" and python_full_version < "4.0.0"
|
|||
bleach==5.0.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a \
|
||||
--hash=sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c
|
||||
bx-django-utils==26; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:c04776c4c6b275ddcadae79fd1578e6ae9ba92d8cf752a9ee4f2b70a22f4236e \
|
||||
--hash=sha256:19349d0a8fa165d87b4fd544efb61418f7d6c41cfabaa46d0153bb6d844262a1
|
||||
bx-py-utils==67; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:4810dcab69146ffd5c31d45710c47fa9ac63f074b26326bc2f17eb7eb7f5e09e \
|
||||
--hash=sha256:981877273d1c480f8d6f1de78b1a034c97b5e420df75e66799b320ff9133a047
|
||||
certifi==2022.6.15; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412 \
|
||||
--hash=sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d
|
||||
charset-normalizer==2.1.0; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" and python_full_version >= "3.6.0" \
|
||||
--hash=sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413 \
|
||||
--hash=sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5
|
||||
bx-django-utils==31; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:bc26ad6c78c43bbf78c9b32ea2ced76dace95ca22bd4acee4ef76a6e5253e3e0 \
|
||||
--hash=sha256:5779673dbce2dfabbbdadcf443bd67273e792da855082e2ea8b26a4e354689bd
|
||||
bx-py-utils==68; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:00c3fbc9b5f48626a0a58141aaa90104349bac9723941c64f528f8742b0961db \
|
||||
--hash=sha256:fe5808c379db7165a51cbf5e4d947ef783d78bdfb5c47665e85e9cfe0b520ff9
|
||||
certifi==2022.9.14; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516 \
|
||||
--hash=sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5
|
||||
charset-normalizer==2.1.1; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" and python_full_version >= "3.6.0" \
|
||||
--hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \
|
||||
--hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f
|
||||
colorama==0.4.5; python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or python_version >= "3.7" and python_full_version < "4.0.0" and sys_platform == "win32" and python_full_version >= "3.5.0" \
|
||||
--hash=sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da \
|
||||
--hash=sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4
|
||||
colorlog==6.6.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:351c51e866c86c3217f08e4b067a7974a678be78f07f85fc2d55b8babde6d94e \
|
||||
--hash=sha256:344f73204009e4c83c5b6beb00b3c45dc70fcdae3c80db919e0a4171d006fde8
|
||||
colorlog==6.7.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \
|
||||
--hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5
|
||||
defusedxml==0.7.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.5.0" \
|
||||
--hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 \
|
||||
--hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69
|
||||
|
@ -37,51 +37,51 @@ diff-match-patch==20200713; python_version >= "3.7" and python_full_version < "4
|
|||
django-admin-sortable2==1.0.4; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:f96044003176c6684c5f969792ca833a505d654fa0f7b24232a0a610e4332a53 \
|
||||
--hash=sha256:e22956889533b48a35a7f02859ae3a939753fa9a7d7d532cefc2835b41bdcebb
|
||||
django-axes==5.36.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:bac08a7047fde26ffb54813c971fd40eeadb4ecb8d342a6e47d53de666d1a792 \
|
||||
--hash=sha256:466e6ed1affd0866c78f245ee658d2619f74250aca5856852d86e61dba400eda
|
||||
django-ckeditor==6.3.2; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:ce0c806e40172dbea35330a207632701a6d418314ae8c8fa140fd277d9322c96 \
|
||||
--hash=sha256:e1580105c9ff6fcaca6345acda1dc01416733027c61c6387e02dd5960b8ade3c
|
||||
django-axes==5.39.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:97702552f7939c81db5bba2ef855ae43f20df92fa261cb79fd4c8633ba3b3955 \
|
||||
--hash=sha256:8f039f8e98f050f13f654efca599d8a04d0b57d330c590cf89ec2bf731c9a7fb
|
||||
django-ckeditor==6.3.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:d04f350f4a200c2a0f96307fc8827bd4e87af5694fb12d53189ba92025b2da37 \
|
||||
--hash=sha256:b5c03d77b9fe848bf12520512a82d07533afa8678040731b1d4d86c1dcea8344
|
||||
django-dbbackup==4.0.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:c2f17877f44ce0d2315e5c3b2ac5f39f1fdf9be49b7fcd0c96e389ddb19ed141 \
|
||||
--hash=sha256:5762039354f2f9c996c008a9eaf3a8e59aa809a1ea594c07d1de5a5e4cd36fa3
|
||||
django-debug-toolbar==3.5.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:97965f2630692de316ea0c1ca5bfa81660d7ba13146dbc6be2059cf55b35d0e5 \
|
||||
--hash=sha256:89a52128309eb4da12738801ff0c202d2ff8730d1c3225fac6acf630c303e661
|
||||
django-import-export==2.8.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:33c37b2921ef84e2cd9aa0eb76d04a7c2b538c9d04cb1ed97ac32600876cab30 \
|
||||
--hash=sha256:31d7dcfba22251e3ef93accb7da844f58c4d78585db9dd7dae37bb76f939da2c
|
||||
django-debug-toolbar==3.6.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:95fc2fd29c56cc86678aae9f6919ececefe892f2a78c4004b193a223a8380c3d \
|
||||
--hash=sha256:fe7fe3f21865218827e2162ecc06eba386dfe8cffe4f3501c49bb4359e06a0e6
|
||||
django-import-export==2.9.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:02ce3a8e191992fa7aa1d660877ac6764fa9e32a5ba6394293f2fc761a5bdd19 \
|
||||
--hash=sha256:126d32a4410c42b6e1bf060355bf45968f6fe427c3b7ed04c96873bd45d7549a
|
||||
django-ipware==4.0.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.6.0" \
|
||||
--hash=sha256:602a58325a4808bd19197fef2676a0b2da2df40d0ecf21be414b2ff48c72ad05 \
|
||||
--hash=sha256:878dbb06a87e25550798e9ef3204ed70a200dd8b15e47dcef848cf08244f04c9
|
||||
django-js-asset==2.0.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:86f9f300d682537ddaf0487dc2ab356581b8f50c069bdba91d334a46e449f923 \
|
||||
--hash=sha256:adc1ee1efa853fad42054b540c02205344bb406c9bddf87c9e5377a41b7db90f
|
||||
django-processinfo==1.0.2; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:3cacad233a5428a5cc6292eafbfddd97948d8d1e4f47e47175a7fcdfcee90f12 \
|
||||
--hash=sha256:08aefdf7285d1eaa595e46570bcc12f2dfd9e24594d524246110614819076b6c
|
||||
django-processinfo==1.1.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:e5d883c2bd4d3a197357bb381a4c19165b5c9ff9a852f96b0dd1ccfd98e2e4a2 \
|
||||
--hash=sha256:c7d1fe2203655925294c860878509fe2a6eb1a5390a170c848023e4619b903da
|
||||
django-redis==5.2.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de \
|
||||
--hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026
|
||||
django-reversion-compare==0.15.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:ed0264a2852d9d867023f1874948b8234dad9c2d2fa22ea18cfd5f28f304d7a0 \
|
||||
--hash=sha256:d6f37b106aec287ae17a076bb7db1184ab02ab1898f0e8693f2779fbdaf71697
|
||||
django-reversion==5.0.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:a2b26a4b84b11338136ca9d6457a4af3070992c7a89623b349009a123f28ea1d \
|
||||
--hash=sha256:45206cc0393fa18b7d5c0332b982736a0f6eb6d2b908ad7cc86e370ce7d4a807
|
||||
django-reversion==5.0.2; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:243a12ee4e04c1611c0f076fbfc3074f1ad40afc45adc64de5ba2414cc4eaf29 \
|
||||
--hash=sha256:5ae3f0a529530bc24afd64b084b690c96d615b70a45bad3a68dc12fcf50ed8c9
|
||||
django-tagulous==1.3.3; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:d445590ae1b5cb9b8c5a425f97bf5f01148a33419c19edeb721ebd9fdd6792fe \
|
||||
--hash=sha256:ad3bb85f4cce83a47e4c0257143229cb92a294defa02fe661823b0442b35d478
|
||||
django-tools==0.50.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:c53805b60f6745d9d3a729d2b0add72eb27284362e0aef73d72b1a69704e4357 \
|
||||
--hash=sha256:4ce9f524ba08d2071a762dc66e7f85ac1664b41cc8fa0ce686a651c1610b3d67
|
||||
django-yunohost-integration==0.2.4; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:f5cdb5480025e90de0221d2b1c6282f517fd0c903702563cccb771cb3e1d9417 \
|
||||
--hash=sha256:a4b3617a3b39225d6162fa88827e9fe8b65388e26a0bbc23ea665c62aa8cb044
|
||||
django==3.2.14; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:a8681e098fa60f7c33a4b628d6fcd3fe983a0939ff1301ecacac21d0b38bad56 \
|
||||
--hash=sha256:677182ba8b5b285a4e072f3ac17ceee6aff1b5ce77fd173cc5b6a2d3dc022fcf
|
||||
django-tools==0.54.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:5040a91282be9d1c9d379b0c65da50bcb3691bff03cee54fd4123ace238c3a43 \
|
||||
--hash=sha256:a7b7bfa5b9c5a81966454d17dffb2403cee25a806c858ee0486a08798227598f
|
||||
django-yunohost-integration==0.4.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:560a280d509f8e28ea4b932d6682c91fab5d50f62b907981b9e0376556c8df7b \
|
||||
--hash=sha256:11a4add7cac2331e06348ef0c3eae597fe01f37867cde1f315ca707625527cdb
|
||||
django==3.2.15; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:115baf5049d5cf4163e43492cdc7139c306ed6d451e7d3571fe9612903903713 \
|
||||
--hash=sha256:f71934b1a822f14a86c9ac9634053689279cd04ae69cb6ade4a59471b886582b
|
||||
et-xmlfile==1.1.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada \
|
||||
--hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c
|
||||
|
@ -90,9 +90,9 @@ gunicorn==20.1.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
|||
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
|
||||
icdiff==2.0.5; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:35d24b728e48b7e0a12bdb69386d3bfc7eef4fe922d0ac1cd70d6e5c11630bae
|
||||
idna==3.3; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \
|
||||
--hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d
|
||||
idna==3.4; python_version >= "3.7" and python_version < "4" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 \
|
||||
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4
|
||||
importlib-metadata==4.2.0; python_version >= "3.7" and python_full_version < "4.0.0" and python_version < "3.8" \
|
||||
--hash=sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b \
|
||||
--hash=sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31
|
||||
|
@ -118,8 +118,8 @@ pillow==9.2.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
|||
--hash=sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e \
|
||||
--hash=sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28 \
|
||||
--hash=sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d \
|
||||
--hash=sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8 \
|
||||
--hash=sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9 \
|
||||
--hash=sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc \
|
||||
--hash=sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437 \
|
||||
--hash=sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004 \
|
||||
--hash=sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0 \
|
||||
--hash=sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4 \
|
||||
|
@ -169,34 +169,30 @@ pillow==9.2.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
|||
pprintpp==0.4.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \
|
||||
--hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403
|
||||
psycopg2==2.8.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||
--hash=sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725 \
|
||||
--hash=sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5 \
|
||||
--hash=sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad \
|
||||
--hash=sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3 \
|
||||
--hash=sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821 \
|
||||
--hash=sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301 \
|
||||
--hash=sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a \
|
||||
--hash=sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d \
|
||||
--hash=sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84 \
|
||||
--hash=sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5 \
|
||||
--hash=sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e \
|
||||
--hash=sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051 \
|
||||
--hash=sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3 \
|
||||
--hash=sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7 \
|
||||
--hash=sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543
|
||||
pyinventory==0.14.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:115673c5d6463ed79544c8faa8ffe8358bc6222f169f7e27ec7ffbbad9951fe3 \
|
||||
--hash=sha256:3e1e1ac4cfdb5f2caca452e4e17d7526901da6eba662c83521895782e3b94321
|
||||
psycopg2==2.9.3; python_version >= "3.6" \
|
||||
--hash=sha256:083707a696e5e1c330af2508d8fab36f9700b26621ccbcb538abe22e15485362 \
|
||||
--hash=sha256:d3ca6421b942f60c008f81a3541e8faf6865a28d5a9b48544b0ee4f40cac7fca \
|
||||
--hash=sha256:9572e08b50aed176ef6d66f15a21d823bb6f6d23152d35e8451d7d2d18fdac56 \
|
||||
--hash=sha256:a81e3866f99382dfe8c15a151f1ca5fde5815fde879348fe5a9884a7c092a305 \
|
||||
--hash=sha256:cb10d44e6694d763fa1078a26f7f6137d69f555a78ec85dc2ef716c37447e4b2 \
|
||||
--hash=sha256:4295093a6ae3434d33ec6baab4ca5512a5082cc43c0505293087b8a46d108461 \
|
||||
--hash=sha256:34b33e0162cfcaad151f249c2649fd1030010c16f4bbc40a604c1cb77173dcf7 \
|
||||
--hash=sha256:0762c27d018edbcb2d34d51596e4346c983bd27c330218c56c4dc25ef7e819bf \
|
||||
--hash=sha256:8cf3878353cc04b053822896bc4922b194792df9df2f1ad8da01fb3043602126 \
|
||||
--hash=sha256:06f32425949bd5fe8f625c49f17ebb9784e1e4fe928b7cce72edc36fb68e4c0c \
|
||||
--hash=sha256:8e841d1bf3434da985cc5ef13e6f75c8981ced601fd70cc6bf33351b91562981
|
||||
pyinventory==0.16.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:ff7d36eb42775f05d2ab12b22f361d1ac7cbf324c25505cb6ec5745371701eb1 \
|
||||
--hash=sha256:130f9f5474928cf1989fb578e453fec75cedabf2ce1425db5bb38f462896a3d8
|
||||
pyparsing==3.0.9; python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.6.8" \
|
||||
--hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc \
|
||||
--hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb
|
||||
python-stdnum==1.17; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:374e2b5e13912ccdbf50b0b23fca2c3e0531174805c32d74e145f37756328340 \
|
||||
--hash=sha256:a46e6cf9652807314d369b654b255c86a59f93d18be2834f3d567ed1a346c547
|
||||
pytz==2022.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c \
|
||||
--hash=sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7
|
||||
pytz==2022.2.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197 \
|
||||
--hash=sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5
|
||||
pyyaml==6.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \
|
||||
--hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \
|
||||
|
@ -205,6 +201,13 @@ pyyaml==6.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
|||
--hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 \
|
||||
--hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \
|
||||
--hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \
|
||||
--hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \
|
||||
--hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \
|
||||
--hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \
|
||||
--hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \
|
||||
--hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \
|
||||
--hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \
|
||||
--hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \
|
||||
--hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \
|
||||
--hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \
|
||||
--hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \
|
||||
|
@ -249,9 +252,9 @@ tablib==3.2.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
|||
typing-extensions==4.3.0; python_version >= "3.7" and python_full_version < "4.0.0" and python_version < "3.8" \
|
||||
--hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \
|
||||
--hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6
|
||||
urllib3==1.26.11; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc \
|
||||
--hash=sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a
|
||||
urllib3==1.26.12; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 \
|
||||
--hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e
|
||||
webencodings==0.5.1; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
||||
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
|
||||
# Please do not modify this file, it will be reset at the next update.
|
||||
# You can edit the file __FINAL_HOME_PATH__/local_settings.py and add/modify the settings you need.
|
||||
# You can edit the file __FINALPATH__/local_settings.py and add/modify the settings you need.
|
||||
# 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.
|
||||
|
||||
|
@ -11,20 +11,19 @@
|
|||
|
||||
from pathlib import Path as __Path
|
||||
|
||||
from django_yunohost_integration.base_settings import * # noqa
|
||||
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 inventory_project.settings.base import * # noqa
|
||||
from inventory_project.settings.base import * # noqa:F401,F403
|
||||
|
||||
|
||||
DEBUG = False # Don't turn DEBUG on in production!
|
||||
from django_yunohost_integration.base_settings import LOGGING # noqa:F401 isort:skip
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
FINAL_HOME_PATH = __Path('__FINAL_HOME_PATH__') # /opt/yunohost/$app
|
||||
assert FINAL_HOME_PATH.is_dir(), f'Directory not exists: {FINAL_HOME_PATH}'
|
||||
FINALPATH = __Path('__FINALPATH__') # /opt/yunohost/$app
|
||||
assert FINALPATH.is_dir(), f'Directory not exists: {FINALPATH}'
|
||||
|
||||
FINAL_WWW_PATH = __Path('__FINAL_WWW_PATH__') # /var/www/$app
|
||||
assert FINAL_WWW_PATH.is_dir(), f'Directory not exists: {FINAL_WWW_PATH}'
|
||||
PUBLIC_PATH = __Path('__PUBLIC_PATH__') # /var/www/$app
|
||||
assert PUBLIC_PATH.is_dir(), f'Directory not exists: {PUBLIC_PATH}'
|
||||
|
||||
LOG_FILE = __Path('__LOG_FILE__') # /var/log/$app/pyinventory.log
|
||||
assert LOG_FILE.is_file(), f'File not exists: {LOG_FILE}'
|
||||
|
@ -33,13 +32,22 @@ PATH_URL = '__PATH_URL__' # $YNH_APP_ARG_PATH
|
|||
PATH_URL = PATH_URL.strip('/')
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# config_panel.toml settings:
|
||||
|
||||
ROOT_URLCONF = 'urls' # /opt/yunohost/pyinventory/ynh_urls.py
|
||||
DEBUG_ENABLED = '__DEBUG_ENABLED__'
|
||||
DEBUG = bool(int(DEBUG_ENABLED))
|
||||
|
||||
LOG_LEVEL = '__LOG_LEVEL__'
|
||||
ADMIN_EMAIL = '__ADMIN_EMAIL__'
|
||||
DEFAULT_FROM_EMAIL = '__DEFAULT_FROM_EMAIL__'
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Function that will be called to finalize a user profile:
|
||||
YNH_SETUP_USER = 'setup_user.setup_project_user'
|
||||
|
||||
SECRET_KEY = __get_or_create_secret(FINAL_HOME_PATH / 'secret.txt') # /opt/yunohost/$app/secret.txt
|
||||
SECRET_KEY = __get_or_create_secret(FINALPATH / 'secret.txt') # /opt/yunohost/$app/secret.txt
|
||||
|
||||
INSTALLED_APPS.append('django_yunohost_integration')
|
||||
|
||||
|
@ -65,18 +73,20 @@ LOGIN_URL = '/yunohost/sso/'
|
|||
LOGOUT_REDIRECT_URL = '/yunohost/sso/'
|
||||
# /yunohost/sso/?action=logout
|
||||
|
||||
ROOT_URLCONF = 'urls' # .../conf/urls.py
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
ADMINS = (('__ADMIN__', '__ADMINMAIL__'),)
|
||||
ADMINS = (('__ADMIN__', ADMIN_EMAIL),)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': '__APP__',
|
||||
'USER': '__APP__',
|
||||
'NAME': '__DB_NAME__',
|
||||
'USER': '__DB_USER__',
|
||||
'PASSWORD': '__DB_PWD__',
|
||||
'HOST': '127.0.0.1',
|
||||
'PORT': '5432', # Default Postgres Port
|
||||
|
@ -95,11 +105,10 @@ EMAIL_SUBJECT_PREFIX = f'[{SITE_TITLE}] '
|
|||
|
||||
|
||||
# E-mail address that error messages come from.
|
||||
SERVER_EMAIL = 'noreply@__DOMAIN__'
|
||||
SERVER_EMAIL = ADMIN_EMAIL
|
||||
|
||||
# Default email address to use for various automated correspondence from
|
||||
# the site managers. Used for registration emails.
|
||||
DEFAULT_FROM_EMAIL = '__ADMINMAIL__'
|
||||
|
||||
# List of URLs your site is supposed to serve
|
||||
ALLOWED_HOSTS = ['__DOMAIN__']
|
||||
|
@ -131,8 +140,8 @@ else:
|
|||
STATIC_URL = '/static/'
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
STATIC_ROOT = str(FINAL_WWW_PATH / 'static')
|
||||
MEDIA_ROOT = str(FINAL_WWW_PATH / 'media')
|
||||
STATIC_ROOT = str(PUBLIC_PATH / 'static')
|
||||
MEDIA_ROOT = str(PUBLIC_PATH / 'media')
|
||||
|
||||
# _____________________________________________________________________________
|
||||
# django-ckeditor
|
||||
|
@ -142,46 +151,22 @@ CKEDITOR_BASEPATH = STATIC_URL + 'ckeditor/ckeditor/'
|
|||
# _____________________________________________________________________________
|
||||
# Django-dbbackup
|
||||
|
||||
DBBACKUP_STORAGE_OPTIONS['location'] = str(FINAL_HOME_PATH / 'backups')
|
||||
DBBACKUP_STORAGE_OPTIONS['location'] = str(FINALPATH / 'backups')
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '{asctime} {levelname} {name} {module}.{funcName} {message}',
|
||||
'style': '{',
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'formatter': 'verbose',
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'include_html': True,
|
||||
},
|
||||
'log_file': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.handlers.WatchedFileHandler',
|
||||
'formatter': 'verbose',
|
||||
'filename': str(LOG_FILE),
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'django': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'axes': {'handlers': ['log_file', 'mail_admins'], 'level': 'WARNING', 'propagate': False},
|
||||
'django_tools': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'django_yunohost_integration': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'inventory': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
},
|
||||
# Set log file to e.g.: /var/log/$app/$app.log
|
||||
LOGGING['handlers']['log_file']['filename'] = str(LOG_FILE)
|
||||
|
||||
LOGGING['loggers']['inventory'] = {
|
||||
'handlers': ['syslog', 'log_file', 'mail_admins'],
|
||||
'level': 'INFO',
|
||||
'propagate': False,
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
from local_settings import * # noqa
|
||||
from local_settings import * # noqa:F401,F403
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=PyInventory application server
|
||||
Description=__APP__ server
|
||||
After=redis.service postgresql.service
|
||||
|
||||
[Service]
|
20
conf/urls.py
20
conf/urls.py
|
@ -1,36 +1,18 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls import include, static
|
||||
from django.conf.urls import include
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
|
||||
|
||||
# def debug_view(request):
|
||||
# """ debug request.META """
|
||||
# if not request.user.is_authenticated:
|
||||
# from django.shortcuts import redirect
|
||||
# return redirect('admin:index')
|
||||
#
|
||||
# import pprint
|
||||
# meta = pprint.pformat(request.META)
|
||||
# html = f'<html><body>request.META: <pre>{meta}</pre></body></html>'
|
||||
# from django.http import HttpResponse
|
||||
# return HttpResponse(html)
|
||||
|
||||
|
||||
if settings.PATH_URL:
|
||||
# settings.PATH_URL is the $YNH_APP_ARG_PATH
|
||||
# Prefix all urls with "PATH_URL":
|
||||
urlpatterns = [
|
||||
# path(f'{settings.PATH_URL}/debug/', debug_view),
|
||||
|
||||
# MEDIA_URL contains the "PATH_URL" already:
|
||||
path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
||||
|
||||
path(f'{settings.PATH_URL}/', admin.site.urls),
|
||||
path(f'{settings.PATH_URL}/ckeditor/', include('ckeditor_uploader.urls')),
|
||||
]
|
||||
if settings.SERVE_FILES:
|
||||
urlpatterns += static.static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
else:
|
||||
# Installed to domain root, without a path prefix
|
||||
# Just use the default project urls.py
|
||||
|
|
35
config_panel.toml
Normal file
35
config_panel.toml
Normal file
|
@ -0,0 +1,35 @@
|
|||
version = "1.0"
|
||||
|
||||
[main]
|
||||
name = "django_example_ynh configuration"
|
||||
services = ["__APP__"]
|
||||
|
||||
[main.config]
|
||||
name = "Configuration Options"
|
||||
|
||||
[main.config.default_from_email]
|
||||
ask = "from email"
|
||||
type = "email"
|
||||
help = "Default email address to use for various automated emails."
|
||||
bind = "default_from_email:__FINALPATH__/settings.py"
|
||||
|
||||
[main.config.admin_email]
|
||||
ask = "ADMIN email"
|
||||
type = "email"
|
||||
help = "EMail address for error emails."
|
||||
bind = "admin_email:__FINALPATH__/settings.py"
|
||||
|
||||
[main.config.debug_enabled]
|
||||
ask = "DEBUG mode"
|
||||
type = "boolean"
|
||||
yes = "1"
|
||||
no = "0"
|
||||
help = "Should be never enabled in production!"
|
||||
bind = "debug_enabled:__FINALPATH__/settings.py"
|
||||
|
||||
[main.config.log_level]
|
||||
type = "string"
|
||||
ask = "Log Level"
|
||||
choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
||||
default = "WARNING"
|
||||
bind = "log_level:__FINALPATH__/settings.py"
|
15
doc/DESCRIPTION.md
Normal file
15
doc/DESCRIPTION.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
[PyInventory](https://github.com/jedie/PyInventory) is a libre web-based management to catalog things including state and location etc. using [Python](https://www.python.org/)/[Django](https://www.djangoproject.com/).
|
||||
|
||||
[](https://dash.yunohost.org/appci/app/pyinventory) [](https://ci-apps.yunohost.org/ci/apps/pyinventory/) [](https://dash.yunohost.org/appci/app/pyinventory)
|
||||
|
||||
[](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml) [](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml) [](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Pull requests welcome ;)
|
||||
|
||||
This package for YunoHost used [django-yunohost-integration](https://github.com/YunoHost-Apps/django_yunohost_integration)
|
||||
|
||||
More screenshots are here: jedie.github.io/tree/master/screenshots/PyInventory
|
152
doc/DISCLAIMER.md
Normal file
152
doc/DISCLAIMER.md
Normal file
|
@ -0,0 +1,152 @@
|
|||
## Settings and upgrades
|
||||
|
||||
Almost everything related to PyInventory's configuration is handled in a `"../conf/settings.py"` file.
|
||||
You can edit the file `/opt/yunohost/pyinventory/local_settings.py` to enable or disable features.
|
||||
|
||||
Test sending emails:
|
||||
|
||||
```bash
|
||||
ssh admin@yourdomain.tld
|
||||
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
||||
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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.
|
||||
To check current ADMINS run:
|
||||
|
||||
```bash
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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'),)" >> /opt/yunohost/pyinventory/local_settings.py
|
||||
```
|
||||
|
||||
To check the effective settings, run this:
|
||||
```bash
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./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
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
* Report a bug about this package: https://github.com/YunoHost-Apps/pyinventory_ynh
|
||||
* Report a bug about PyInventory itself: https://github.com/jedie/PyInventory
|
||||
* YunoHost website: https://yunohost.org/
|
||||
|
||||
---
|
||||
|
||||
# Developer info
|
||||
|
||||
## package installation / debugging
|
||||
|
||||
Please send your pull request to https://github.com/YunoHost-Apps/pyinventory_ynh
|
||||
|
||||
Try 'main' branch, e.g.:
|
||||
```bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug
|
||||
or
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug
|
||||
```
|
||||
|
||||
Try 'testing' branch, e.g.:
|
||||
```bash
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
or
|
||||
sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
To remove call e.g.:
|
||||
```bash
|
||||
sudo yunohost app remove pyinventory
|
||||
```
|
||||
|
||||
Backup / remove / restore cycle, e.g.:
|
||||
```bash
|
||||
yunohost backup create --apps pyinventory
|
||||
yunohost backup list
|
||||
archives:
|
||||
- pyinventory-pre-upgrade1
|
||||
- 20201223-163434
|
||||
yunohost app remove pyinventory
|
||||
yunohost backup restore 20201223-163434 --apps pyinventory
|
||||
```
|
||||
|
||||
Debug installation, e.g.:
|
||||
```bash
|
||||
root@yunohost:~# ls -la /var/www/pyinventory/
|
||||
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 /opt/yunohost/pyinventory/
|
||||
total 58
|
||||
drwxr-xr-x 5 pyinventory pyinventory 11 Dec 8 08:39 .
|
||||
drwxr-xr-x 3 root root 3 Dec 8 08:36 ..
|
||||
-rw-r--r-- 1 pyinventory pyinventory 460 Dec 8 08:39 gunicorn.conf.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 0 Dec 8 08:39 local_settings.py
|
||||
-rwxr-xr-x 1 pyinventory pyinventory 274 Dec 8 08:39 manage.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 171 Dec 8 08:39 secret.txt
|
||||
drwxr-xr-x 6 pyinventory pyinventory 6 Dec 8 08:37 venv
|
||||
-rw-r--r-- 1 pyinventory pyinventory 115 Dec 8 08:39 wsgi.py
|
||||
-rw-r--r-- 1 pyinventory pyinventory 4737 Dec 8 08:39 settings.py
|
||||
|
||||
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
||||
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py check
|
||||
PyInventory v0.8.2 (Django v2.2.17)
|
||||
DJANGO_SETTINGS_MODULE='settings'
|
||||
PROJECT_PATH:/opt/yunohost/pyinventory/venv/lib/python3.7/site-packages
|
||||
BASE_PATH:/opt/yunohost/pyinventory
|
||||
System check identified no issues (0 silenced).
|
||||
|
||||
root@yunohost:~# tail -f /var/log/pyinventory/pyinventory.log
|
||||
root@yunohost:~# cat /etc/systemd/system/pyinventory.service
|
||||
|
||||
root@yunohost:~# systemctl reload-or-restart pyinventory
|
||||
root@yunohost:~# journalctl --unit=pyinventory --follow
|
||||
```
|
||||
|
||||
## local test
|
||||
|
||||
For quicker developing of PyInventory in the context of YunoHost app,
|
||||
it's possible to run the Django developer server with the settings
|
||||
and urls made for YunoHost installation.
|
||||
|
||||
e.g.:
|
||||
```bash
|
||||
~$ git clone https://github.com/YunoHost-Apps/pyinventory_ynh.git
|
||||
~$ cd pyinventory_ynh/
|
||||
~/pyinventory_ynh$ make
|
||||
install-poetry install or update poetry
|
||||
install install PyInventory via poetry
|
||||
update update the sources and installation
|
||||
local-test Run local_test.py to run pyinventory_ynh locally
|
||||
~/pyinventory_ynh$ make install-poetry
|
||||
~/pyinventory_ynh$ make install
|
||||
~/pyinventory_ynh$ make local-test
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* SQlite database will be used
|
||||
* A super user with username `test` and password `test` is created
|
||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
0
doc/screenshots/gitkeep
Normal file
0
doc/screenshots/gitkeep
Normal file
BIN
doc/screenshots/pyinventory_v010_screenshot_2.png
Normal file
BIN
doc/screenshots/pyinventory_v010_screenshot_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 163 KiB |
BIN
doc/screenshots/pyinventory_v010_screenshot_3.png
Normal file
BIN
doc/screenshots/pyinventory_v010_screenshot_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
BIN
doc/screenshots/pyinventory_v0110_screenshot_memo_1.png
Normal file
BIN
doc/screenshots/pyinventory_v0110_screenshot_memo_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
BIN
doc/screenshots/pyinventory_v020_screenshot_1.png
Normal file
BIN
doc/screenshots/pyinventory_v020_screenshot_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
|
@ -22,6 +22,9 @@ def main():
|
|||
django_settings_path=BASE_PATH / 'conf' / 'settings.py',
|
||||
destination=BASE_PATH / 'local_test',
|
||||
runserver=True,
|
||||
extra_replacements={
|
||||
'__DEBUG_ENABLED__': '1',
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,13 @@
|
|||
"description": {
|
||||
"en": "Web based management to catalog things including state and location etc."
|
||||
},
|
||||
"version": "0.14.0~ynh1",
|
||||
"version": "0.16.0~ynh1",
|
||||
"url": "https://github.com/jedie/PyInventory",
|
||||
"upstream": {
|
||||
"license": "GPL-3.0",
|
||||
"website": "https://github.com/jedie/PyInventory",
|
||||
"code": "https://github.com/jedie/PyInventory"
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
"maintainer": {
|
||||
"name": "Jens Diemer",
|
||||
|
@ -14,18 +19,17 @@
|
|||
},
|
||||
"previous_maintainers": [],
|
||||
"requirements": {
|
||||
"yunohost": ">= 4.0"
|
||||
"yunohost": ">= 4.4"
|
||||
},
|
||||
"multi_instance": true,
|
||||
"services": [
|
||||
"nginx"
|
||||
"nginx", "postgresql", "redis"
|
||||
],
|
||||
"arguments": {
|
||||
"install" : [
|
||||
{
|
||||
"name": "domain",
|
||||
"type": "domain",
|
||||
"example": "domain.org"
|
||||
"type": "domain"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
|
@ -35,9 +39,8 @@
|
|||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"type": "user",
|
||||
"example": "johndoe"
|
||||
}
|
||||
]
|
||||
"type": "user"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
614
poetry.lock
generated
614
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,20 +1,19 @@
|
|||
[tool.poetry]
|
||||
name = "pyinventory_ynh"
|
||||
version = "0.14.0~ynh1"
|
||||
version = "0.16.0~ynh1"
|
||||
description = "Test pyinventory_ynh via local_test.py"
|
||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
||||
license = "GPL"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
# Keep Python 3.7 until Yunohost contains a newer Python Version ;)
|
||||
python = ">=3.7,<4.0.0"
|
||||
pyinventory = {version = ">=0.14.0", extras = ["psycopg2-source"]}
|
||||
pyinventory = {version = ">=0.16.0", extras = ["psycopg2-source"]}
|
||||
|
||||
# Note: "ynh" extras will install gunicorn, psycopg2, django-redis and django-axes
|
||||
django_yunohost_integration = {version = ">=v0.2.0", extras = ["ynh"]}
|
||||
django_yunohost_integration = {version = "*", extras = ["ynh"]}
|
||||
|
||||
# TODO: Update psycopg2 after PyInventory updates Django >2.2 update
|
||||
# See: https://github.com/psycopg/psycopg2/issues/1293
|
||||
psycopg2 = "<2.9" # https://www.psycopg.org/docs/install.html#build-prerequisites
|
||||
psycopg2 = "*" # https://github.com/psycopg/psycopg2/
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
bx_py_utils = "*"
|
||||
|
@ -23,14 +22,16 @@ pytest = "*"
|
|||
pytest-cov = "*"
|
||||
pytest-django = "*"
|
||||
pytest-darker = "*" # https://github.com/akaihola/pytest-darker
|
||||
pytest-flake8 = "*"
|
||||
pytest-isort = "*"
|
||||
flake8 = "*"
|
||||
isort = "*"
|
||||
coveralls = "*"
|
||||
flynt = "*"
|
||||
pyupgrade = "*"
|
||||
EditorConfig = "*" # https://github.com/editorconfig/editorconfig-core-py
|
||||
safety = "*" # https://github.com/pyupio/safety
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
|
||||
|
@ -59,15 +60,15 @@ line_length = 120
|
|||
atomic=true
|
||||
profile='black'
|
||||
line_length=120
|
||||
skip_glob=["*/htmlcov/*","*/migrations/*"]
|
||||
known_first_party=["inventory"]
|
||||
skip_glob=["*/htmlcov/*","*/migrations/*","*/local_test/*"]
|
||||
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 coverage* dist htmlcov"
|
||||
norecursedirs = ".* .git __pycache__ conf local_test coverage* dist htmlcov"
|
||||
# sometimes helpfull "addopts" arguments:
|
||||
# -vv
|
||||
# --verbose
|
||||
|
@ -76,7 +77,6 @@ norecursedirs = ".* .git __pycache__ conf coverage* dist htmlcov"
|
|||
# --full-trace
|
||||
# -p no:warnings
|
||||
addopts = """
|
||||
--import-mode=importlib
|
||||
--reuse-db
|
||||
--nomigrations
|
||||
--cov=.
|
||||
|
@ -86,21 +86,22 @@ addopts = """
|
|||
--no-cov-on-fail
|
||||
--showlocals
|
||||
--darker
|
||||
--flake8
|
||||
--isort
|
||||
--doctest-modules
|
||||
--failed-first
|
||||
--last-failed-no-failures all
|
||||
--new-first
|
||||
"""
|
||||
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = [".*"]
|
||||
|
||||
|
||||
[tool.tox]
|
||||
# https://tox.readthedocs.io/en/latest/example/basic.html#pyproject-toml-tox-legacy-ini
|
||||
legacy_tox_ini = """
|
||||
[tox]
|
||||
isolated_build = True
|
||||
envlist = py39,py38,py37
|
||||
envlist = py{37,38,39,310}
|
||||
skip_missing_interpreters = True
|
||||
|
||||
[testenv]
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
"""
|
||||
Run pytest against local test creation
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
try:
|
||||
from django_yunohost_integration.pytest_helper import run_pytest
|
||||
except ImportError as err:
|
||||
raise ImportError('Did you forget to activate a virtual environment?') from err
|
||||
|
||||
|
||||
BASE_PATH = Path(__file__).parent
|
||||
|
||||
|
||||
def main():
|
||||
run_pytest(
|
||||
django_settings_path=BASE_PATH / 'conf' / 'settings.py',
|
||||
destination=BASE_PATH / 'local_test',
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -13,6 +13,22 @@ app=$YNH_APP_INSTANCE_NAME
|
|||
# Currently not used: PyInventory has no public pages, yet!
|
||||
is_public=$YNH_APP_ARG_IS_PUBLIC
|
||||
|
||||
#=================================================
|
||||
# ARGUMENTS FROM CONFIG PANEL
|
||||
#=================================================
|
||||
|
||||
# 'debug_enabled' -> '__DEBUG_ENABLED__' -> settings.DEBUG
|
||||
debug_enabled="0"
|
||||
|
||||
# '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
|
||||
#=================================================
|
||||
|
@ -20,7 +36,7 @@ is_public=$YNH_APP_ARG_IS_PUBLIC
|
|||
public_path=/var/www/$app
|
||||
final_path=/opt/yunohost/$app
|
||||
log_path=/var/log/$app
|
||||
log_file="${log_path}/pyinventory.log"
|
||||
log_file="${log_path}/${app}.log"
|
||||
|
||||
#=================================================
|
||||
# COMMON VARIABLES
|
||||
|
@ -71,17 +87,3 @@ ynh_redis_remove_db() {
|
|||
redis-cli -n "$db" flushall
|
||||
}
|
||||
|
||||
#=================================================
|
||||
|
||||
# Execute a command as another user
|
||||
# usage: ynh_exec_as USER COMMAND [ARG ...]
|
||||
ynh_exec_as() {
|
||||
local USER=$1
|
||||
shift 1
|
||||
|
||||
if [[ $USER = $(whoami) ]]; then
|
||||
eval "$@"
|
||||
else
|
||||
sudo -u "$USER" "$@"
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
YNH_APP_ARG_DOMAIN=$YNH_APP_NEW_DOMAIN
|
||||
YNH_APP_ARG_PATH=$YNH_APP_NEW_PATH
|
||||
|
||||
source _common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
|
@ -30,10 +33,21 @@ final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
|||
log_path=$(ynh_app_setting_get --app="$app" --key=log_path)
|
||||
|
||||
port=$(ynh_app_setting_get --app="$app" --key=port)
|
||||
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
admin_mail=$(ynh_user_get_info "$admin" mail)
|
||||
db_name=$(ynh_sanitize_dbid --db_name="$app")
|
||||
db_user=$db_name
|
||||
|
||||
redis_db=$(ynh_app_setting_get --app="$app" --key=redis_db)
|
||||
|
||||
#-------------------------------------------------
|
||||
# config_panel.toml settings:
|
||||
|
||||
debug_enabled=$(ynh_app_setting_get --app="$app" --key=debug_enabled)
|
||||
log_level=$(ynh_app_setting_get --app="$app" --key=log_level)
|
||||
admin_email=$(ynh_app_setting_get --app="$app" --key=admin_email)
|
||||
default_from_email=$(ynh_app_setting_get --app="$app" --key=default_from_email)
|
||||
|
||||
#=================================================
|
||||
# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
|
||||
#=================================================
|
||||
|
@ -72,7 +86,7 @@ fi
|
|||
#=================================================
|
||||
# STOP SYSTEMD SERVICE
|
||||
#=================================================
|
||||
ynh_script_progression --message="Stopping systemd services..."
|
||||
ynh_script_progression --message="Stopping systemd service '$app'..."
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="stop"
|
||||
|
||||
|
@ -112,36 +126,19 @@ fi
|
|||
#=================================================
|
||||
# MODIFY SETTINGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Modify PyInventory's config file..."
|
||||
ynh_script_progression --message="Modify $app config file..."
|
||||
|
||||
# save old settings file
|
||||
settings="$final_path/settings.py"
|
||||
ynh_backup_if_checksum_is_different --file="$settings"
|
||||
domain=$YNH_APP_NEW_DOMAIN
|
||||
path_url=$YNH_APP_NEW_PATH
|
||||
|
||||
cp "../conf/settings.py" "$settings"
|
||||
|
||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
# Difference to install/upgrade scripts: Use $new_domain and $new_path here:
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$new_domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$new_path" --target_file="$settings"
|
||||
|
||||
# Recalculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
ynh_add_config --template="settings.py" --destination="$final_path/settings.py"
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALISATION
|
||||
#=================================================
|
||||
# START SYSTEMD SERVICE
|
||||
#=================================================
|
||||
ynh_script_progression --message="Starting systemd services..." --weight=5
|
||||
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="start"
|
||||
|
||||
|
|
|
@ -50,19 +50,29 @@ ynh_app_setting_set --app="$app" --key=path --value="$path_url"
|
|||
# Find a free port
|
||||
port=$(ynh_find_port --port=8000)
|
||||
# Set port as application setting
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/data/helpers.d/setting
|
||||
# https://yunohost.org/en/contribute/packaging_apps/helpers
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/helpers/setting
|
||||
ynh_app_setting_set --app="$app" --key=port --value="$port"
|
||||
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
admin_mail=$(ynh_user_get_info --username="$admin" --key=mail)
|
||||
|
||||
redis_db=$(ynh_redis_get_free_db)
|
||||
ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
||||
|
||||
#-------------------------------------------------
|
||||
# config_panel.toml settings:
|
||||
|
||||
ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled"
|
||||
ynh_app_setting_set --app="$app" --key=log_level --value="$log_level"
|
||||
ynh_app_setting_set --app="$app" --key=admin_email --value="$admin_email"
|
||||
ynh_app_setting_set --app="$app" --key=default_from_email --value="$default_from_email"
|
||||
|
||||
#=================================================
|
||||
# STANDARD MODIFICATIONS
|
||||
#=================================================
|
||||
# INSTALL DEPENDENCIES
|
||||
#=================================================
|
||||
ynh_script_progression --message="Installing dependencies..." --weight=20
|
||||
ynh_script_progression --message="Installing $app dependencies..." --weight=20
|
||||
|
||||
ynh_exec_warn_less ynh_install_app_dependencies "$pkg_dependencies"
|
||||
|
||||
|
@ -86,21 +96,22 @@ ynh_psql_setup_db --db_user="$db_user" --db_name="$db_name"
|
|||
ynh_script_progression --message="Configuring nginx web server..."
|
||||
|
||||
# Create a dedicated nginx config
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/data/helpers.d/nginx
|
||||
# https://yunohost.org/en/contribute/packaging_apps/helpers
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx
|
||||
ynh_add_nginx_config "public_path" "port"
|
||||
|
||||
#=================================================
|
||||
# CREATE DEDICATED USER
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring system user..."
|
||||
ynh_script_progression --message="Configuring system user '$app'..."
|
||||
|
||||
# A home directory for venv and settings etc.
|
||||
ynh_system_user_create --username="$app" --home_dir="$final_path" --use_shell
|
||||
|
||||
#=================================================
|
||||
# PIP INSTALLATION
|
||||
# PYTHON VIRTUALENV
|
||||
#=================================================
|
||||
ynh_script_progression --message="Install project via pip..." --weight=50
|
||||
ynh_script_progression --message="Create Python virtualenv..." --weight=5
|
||||
|
||||
# Always recreate everything fresh with current python version
|
||||
ynh_secure_remove "${final_path}/venv"
|
||||
|
@ -111,6 +122,11 @@ python3 -m venv --without-pip "${final_path}/venv"
|
|||
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
||||
chown -R "$app:" "$final_path"
|
||||
|
||||
#=================================================
|
||||
# PIP INSTALLATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Install project via pip..." --weight=45
|
||||
|
||||
#run source in a 'sub shell'
|
||||
(
|
||||
set +o nounset
|
||||
|
@ -124,43 +140,17 @@ chown -R "$app:" "$final_path"
|
|||
#=================================================
|
||||
# copy config files
|
||||
# ================================================
|
||||
ynh_script_progression --message="Create project configuration files..."
|
||||
ynh_script_progression --message="Create $app configuration files..."
|
||||
|
||||
gunicorn_conf="$final_path/gunicorn.conf.py"
|
||||
cp "../conf/gunicorn.conf.py" "$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$gunicorn_conf"
|
||||
ynh_store_file_checksum --file="$gunicorn_conf"
|
||||
ynh_add_config --template="gunicorn.conf.py" --destination="$final_path/gunicorn.conf.py"
|
||||
|
||||
cp ../conf/manage.py "$final_path/manage.py"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$final_path/manage.py"
|
||||
ynh_store_file_checksum --file="$final_path/manage.py"
|
||||
ynh_add_config --template="manage.py" --destination="$final_path/manage.py"
|
||||
chmod +x "$final_path/manage.py"
|
||||
|
||||
settings="$final_path/settings.py"
|
||||
cp "../conf/settings.py" "$settings"
|
||||
|
||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
|
||||
# Calculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
|
||||
ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
||||
|
||||
cp ../conf/setup_user.py "$final_path/setup_user.py"
|
||||
cp ../conf/urls.py "$final_path/urls.py"
|
||||
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
||||
ynh_add_config --template="settings.py" --destination="$final_path/settings.py"
|
||||
ynh_add_config --template="setup_user.py" --destination="$final_path/setup_user.py"
|
||||
ynh_add_config --template="urls.py" --destination="$final_path/urls.py"
|
||||
ynh_add_config --template="wsgi.py" --destination="$final_path/wsgi.py"
|
||||
|
||||
touch "$final_path/local_settings.py"
|
||||
|
||||
|
@ -178,7 +168,7 @@ cd "$final_path" || exit
|
|||
./manage.py collectstatic --no-input
|
||||
|
||||
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||
./manage.py create_superuser --username="$admin" --email="$admin_mail"
|
||||
./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.
|
||||
|
@ -198,7 +188,7 @@ ynh_use_logrotate "$log_file"
|
|||
#=================================================
|
||||
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||
|
||||
yunohost service add $app --description="Web based management to catalog things" --log="${log_file}"
|
||||
yunohost service add $app --log="${log_file}"
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
|
@ -218,15 +208,29 @@ chmod o-rwx "$final_path"
|
|||
#=================================================
|
||||
# SETUP SYSTEMD
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring a systemd service..."
|
||||
ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5
|
||||
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/data/helpers.d/systemd
|
||||
ynh_add_systemd_config --service="$app" --template="pyinventory.service"
|
||||
# https://yunohost.org/en/contribute/packaging_apps/helpers
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/helpers/systemd
|
||||
ynh_add_systemd_config --service="$app" --template="systemd.service"
|
||||
|
||||
#=================================================
|
||||
# Start pyinventory via systemd
|
||||
# SETUP SSOWAT
|
||||
#=================================================
|
||||
ynh_script_progression --message="Starting PyInventory's services..." --weight=5
|
||||
ynh_script_progression --message="Configuring SSOwat..."
|
||||
|
||||
# Make app public if necessary or protect it
|
||||
if [ $is_public -eq 1 ]
|
||||
then
|
||||
# Everyone can access the app.
|
||||
# The "main" permission is automatically created before the install script.
|
||||
ynh_permission_update --permission "main" --add "visitors"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# Start the app server via systemd
|
||||
#=================================================
|
||||
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="start"
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ fi
|
|||
#=================================================
|
||||
# STOP PYINVENTORY'S SERVICES
|
||||
#=================================================
|
||||
ynh_script_progression --message="Stopping and removing systemd services..." --weight=5
|
||||
ynh_script_progression --message="Stopping and removing systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_remove_systemd_config --service="$app"
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ ynh_abort_if_errors
|
|||
#=================================================
|
||||
ynh_script_progression --message="Loading settings..."
|
||||
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
db_name=$(ynh_app_setting_get --app="$app" --key=db_name)
|
||||
db_user=$db_name
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
|
@ -34,8 +34,6 @@ path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
|||
#=================================================
|
||||
ynh_script_progression --message="Validating restoration parameters..."
|
||||
|
||||
ynh_webpath_available --domain=$domain --path_url=$path_url \
|
||||
|| ynh_die --message="Path not available: ${domain}${path_url}"
|
||||
test ! -d $final_path \
|
||||
|| ynh_die --message="There is already a directory: $final_path "
|
||||
|
||||
|
@ -50,12 +48,10 @@ ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
|||
#=================================================
|
||||
# RESTORE THE APP MAIN DIR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Restoring the app main directory..."
|
||||
ynh_script_progression --message="Restoring $app main directory..."
|
||||
|
||||
ynh_restore_file --origin_path="$public_path"
|
||||
ynh_restore_file --origin_path="$final_path"
|
||||
|
||||
touch "$final_path/local_settings.py"
|
||||
ynh_restore_file --origin_path="$public_path"
|
||||
|
||||
#=================================================
|
||||
# RECREATE THE DEDICATED USER
|
||||
|
@ -83,10 +79,10 @@ ynh_script_progression --message="Reinstalling dependencies..." --weight=20
|
|||
ynh_exec_warn_less ynh_install_app_dependencies "$pkg_dependencies"
|
||||
|
||||
#=================================================
|
||||
# REINSTALL PYTHON VIRTUALENV
|
||||
# PYTHON VIRTUALENV
|
||||
# Maybe the backup contains a other Python version
|
||||
#=================================================
|
||||
ynh_script_progression --message="Upgrade Python virtualenv..." --weight=50
|
||||
ynh_script_progression --message="Recreate Python virtualenv..." --weight=5
|
||||
|
||||
# Always recreate everything fresh with current python version
|
||||
ynh_secure_remove "${final_path}/venv"
|
||||
|
@ -95,6 +91,10 @@ ynh_secure_remove "${final_path}/venv"
|
|||
python3 -m venv --without-pip "${final_path}/venv"
|
||||
chown -R "$app:" "$final_path"
|
||||
|
||||
#=================================================
|
||||
# PIP INSTALLATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Install project via pip..." --weight=45
|
||||
#run source in a 'sub shell'
|
||||
(
|
||||
set +o nounset
|
||||
|
@ -127,7 +127,7 @@ systemctl enable $app.service --quiet
|
|||
#=================================================
|
||||
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||
|
||||
yunohost service add $app --description="Web based management to catalog things" --log="${log_file}"
|
||||
yunohost service add $app --log="${log_file}"
|
||||
|
||||
#=================================================
|
||||
# RESTORE THE LOGROTATE CONFIGURATION
|
||||
|
@ -158,7 +158,7 @@ chmod o-rwx "$final_path"
|
|||
#=================================================
|
||||
# START PYINVENTORY
|
||||
#=================================================
|
||||
ynh_script_progression --message="Starting a systemd service..." --weight=5
|
||||
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="start"
|
||||
|
||||
|
|
106
scripts/upgrade
106
scripts/upgrade
|
@ -21,14 +21,44 @@ domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
|||
path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
||||
|
||||
port=$(ynh_app_setting_get --app="$app" --key=port)
|
||||
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
admin_mail=$(ynh_user_get_info "$admin" mail)
|
||||
db_name=$(ynh_sanitize_dbid --db_name="$app")
|
||||
db_user=$db_name
|
||||
|
||||
redis_db=$(ynh_app_setting_get --app="$app" --key=redis_db)
|
||||
|
||||
#-------------------------------------------------
|
||||
# config_panel.toml settings:
|
||||
|
||||
debug_enabled=$(ynh_app_setting_get --app="$app" --key=debug_enabled)
|
||||
if [ -z "$debug_enabled" ]; then
|
||||
debug_enabled="0"
|
||||
ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled"
|
||||
fi
|
||||
|
||||
log_level=$(ynh_app_setting_get --app="$app" --key=log_level)
|
||||
if [ -z "$log_level" ]; then
|
||||
log_level="WARNING"
|
||||
ynh_app_setting_set --app="$app" --key=log_level --value="$log_level"
|
||||
fi
|
||||
|
||||
admin_email=$(ynh_app_setting_get --app="$app" --key=admin_email)
|
||||
if [ -z "$admin_email" ]; then
|
||||
admin_email="${admin}@${domain}"
|
||||
ynh_app_setting_set --app="$app" --key=admin_email --value="$admin_email"
|
||||
fi
|
||||
|
||||
default_from_email=$(ynh_app_setting_get --app="$app" --key=default_from_email)
|
||||
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
|
||||
|
||||
#=================================================
|
||||
# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
|
||||
#=================================================
|
||||
ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=40
|
||||
ynh_script_progression --message="Backing up $app before upgrading (may take a while)..." --weight=40
|
||||
|
||||
# Backup the current version of the app
|
||||
ynh_backup_before_upgrade
|
||||
|
@ -44,7 +74,7 @@ ynh_abort_if_errors
|
|||
#=================================================
|
||||
# STOP SYSTEMD SERVICE
|
||||
#=================================================
|
||||
ynh_script_progression --message="Stopping systemd services..." --weight=5
|
||||
ynh_script_progression --message="Stopping systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="stop"
|
||||
|
||||
|
@ -54,7 +84,8 @@ ynh_systemd_action --service_name="$app" --action="stop"
|
|||
ynh_script_progression --message="Upgrading nginx web server configuration..."
|
||||
|
||||
# Create a dedicated nginx config
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/data/helpers.d/nginx
|
||||
# https://yunohost.org/en/contribute/packaging_apps/helpers
|
||||
# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx
|
||||
ynh_add_nginx_config "public_path" "port"
|
||||
|
||||
#=================================================
|
||||
|
@ -77,14 +108,14 @@ ynh_system_user_create --username="$app" --home_dir="$final_path" --use_shell
|
|||
#=================================================
|
||||
# SETUP SYSTEMD
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring a systemd service..."
|
||||
ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_add_systemd_config --service="$app" --template="pyinventory.service"
|
||||
ynh_add_systemd_config --service="$app" --template="systemd.service"
|
||||
|
||||
#=================================================
|
||||
# UPGRADE VENV
|
||||
# PYTHON VIRTUALENV
|
||||
#=================================================
|
||||
ynh_script_progression --message="Upgrade project via pip..." --weight=50
|
||||
ynh_script_progression --message="Recreate Python virtualenv..." --weight=5
|
||||
|
||||
# Always recreate everything fresh with current python version
|
||||
ynh_secure_remove "${final_path}/venv"
|
||||
|
@ -95,6 +126,10 @@ python3 -m venv --without-pip "${final_path}/venv"
|
|||
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
||||
chown -R "$app:" "$final_path"
|
||||
|
||||
#=================================================
|
||||
# PIP INSTALLATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Install project via pip..." --weight=45
|
||||
#run source in a 'sub shell'
|
||||
(
|
||||
set +o nounset
|
||||
|
@ -110,50 +145,15 @@ chown -R "$app:" "$final_path"
|
|||
# ================================================
|
||||
ynh_script_progression --message="Create project configuration files..."
|
||||
|
||||
gunicorn_conf="$final_path/gunicorn.conf.py"
|
||||
ynh_backup_if_checksum_is_different --file="$gunicorn_conf"
|
||||
cp "../conf/gunicorn.conf.py" "$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$gunicorn_conf"
|
||||
ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$gunicorn_conf"
|
||||
ynh_store_file_checksum --file="$gunicorn_conf"
|
||||
ynh_add_config --template="gunicorn.conf.py" --destination="$final_path/gunicorn.conf.py"
|
||||
|
||||
cp ../conf/manage.py "$final_path/manage.py"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$final_path/manage.py"
|
||||
ynh_store_file_checksum --file="$final_path/manage.py"
|
||||
ynh_add_config --template="manage.py" --destination="$final_path/manage.py"
|
||||
chmod +x "$final_path/manage.py"
|
||||
|
||||
# save old settings file
|
||||
settings="$final_path/settings.py"
|
||||
ynh_backup_if_checksum_is_different --file="$settings"
|
||||
|
||||
cp "../conf/settings.py" "$settings"
|
||||
|
||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
|
||||
# Recalculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$final_path/setup_user.py"
|
||||
cp ../conf/setup_user.py "$final_path/setup_user.py"
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$final_path/urls.py"
|
||||
cp ../conf/urls.py "$final_path/urls.py"
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$final_path/wsgi.py"
|
||||
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
||||
|
||||
touch "$final_path/local_settings.py"
|
||||
ynh_add_config --template="settings.py" --destination="$final_path/settings.py"
|
||||
ynh_add_config --template="setup_user.py" --destination="$final_path/setup_user.py"
|
||||
ynh_add_config --template="urls.py" --destination="$final_path/urls.py"
|
||||
ynh_add_config --template="wsgi.py" --destination="$final_path/wsgi.py"
|
||||
|
||||
#=================================================
|
||||
# MIGRATE PYINVENTORY
|
||||
|
@ -169,7 +169,7 @@ cd "$final_path" || exit
|
|||
./manage.py collectstatic --no-input
|
||||
|
||||
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||
./manage.py create_superuser --username="$admin" --email="$admin_mail"
|
||||
./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.
|
||||
|
@ -189,7 +189,7 @@ ynh_use_logrotate --non-append
|
|||
#=================================================
|
||||
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||
|
||||
yunohost service add $app --description="Web based management to catalog things" --log="${log_file}"
|
||||
yunohost service add $app --log="${log_file}"
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
|
@ -207,9 +207,9 @@ chmod o-rwx "$public_path"
|
|||
chmod o-rwx "$final_path"
|
||||
|
||||
#=================================================
|
||||
# Start pyinventory via systemd
|
||||
# Start the app server via systemd
|
||||
#=================================================
|
||||
ynh_script_progression --message="Starting PyInventory's services..." --weight=5
|
||||
ynh_script_progression --message="Starting systemd service '$app'..." --weight=5
|
||||
|
||||
ynh_systemd_action --service_name="$app" --action="start"
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Test to create the python virtual env and install all requirements.
|
||||
# Note: Maybe you didn't have all OS packages installed ;)
|
||||
|
||||
set -e
|
||||
|
||||
final_path="./local_test"
|
||||
|
||||
set -x
|
||||
|
||||
mkdir -p "${final_path}/"
|
||||
python3 -m venv "${final_path}/venv"
|
||||
source "${final_path}/venv/bin/activate"
|
||||
|
||||
$final_path/venv/bin/pip install --upgrade wheel pip
|
||||
$final_path/venv/bin/pip install --no-deps -r "./conf/requirements.txt"
|
43
tests/conftest.py
Normal file
43
tests/conftest.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
Special pytest init:
|
||||
|
||||
- Build a "local_test" YunoHost installation
|
||||
- init Django with this local test installation
|
||||
|
||||
So the pytests will run against this local test installation
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import django
|
||||
from django_yunohost_integration.local_test import create_local_test
|
||||
|
||||
|
||||
BASE_PATH = Path(__file__).parent.parent
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||
|
||||
|
||||
def pytest_configure():
|
||||
print('Compile YunoHost files...')
|
||||
final_path = create_local_test(
|
||||
django_settings_path=BASE_PATH / 'conf' / 'settings.py',
|
||||
destination=BASE_PATH / 'local_test',
|
||||
runserver=False,
|
||||
extra_replacements={
|
||||
'__DEBUG_ENABLED__': '0',
|
||||
'__LOG_LEVEL__': 'INFO',
|
||||
'__ADMIN_EMAIL__': 'foo-bar@test.tld',
|
||||
'__DEFAULT_FROM_EMAIL__': 'django_app@test.tld',
|
||||
},
|
||||
)
|
||||
print('Local test files created here:')
|
||||
print(f'"{final_path}"')
|
||||
|
||||
os.chdir(final_path)
|
||||
final_home_str = str(final_path)
|
||||
if final_home_str not in sys.path:
|
||||
sys.path.insert(0, final_home_str)
|
||||
|
||||
django.setup()
|
|
@ -27,17 +27,24 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
assert settings.configured is True
|
||||
|
||||
assert settings.PATH_URL == 'app_path'
|
||||
assert settings.ROOT_URLCONF == 'urls'
|
||||
assert reverse('admin:index') == '/app_path/'
|
||||
|
||||
def assert_path(path, end_text):
|
||||
assert isinstance(path, Path)
|
||||
path = str(path)
|
||||
assert path.endswith(end_text)
|
||||
|
||||
assert_path(settings.FINAL_HOME_PATH, '/local_test/opt_yunohost')
|
||||
assert_path(settings.FINAL_WWW_PATH, '/local_test/var_www')
|
||||
assert_path(settings.FINALPATH, '/local_test/opt_yunohost')
|
||||
assert_path(settings.PUBLIC_PATH, '/local_test/var_www')
|
||||
assert_path(settings.LOG_FILE, '/local_test/var_log_pyinventory.log')
|
||||
|
||||
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_urls(self):
|
||||
assert reverse('admin:index') == '/app_path/'
|
||||
|
@ -66,7 +73,6 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
response = self.client.get('/app_path/', secure=True)
|
||||
self.assertRedirects(response, expected_url='/app_path/login/?next=/app_path/', fetch_redirect_response=False)
|
||||
|
||||
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||
def test_create_unknown_user(self):
|
||||
assert User.objects.count() == 0
|
||||
|
||||
|
@ -77,6 +83,7 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
HTTP_REMOTE_USER='test',
|
||||
HTTP_AUTH_USER='test',
|
||||
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||
secure=True,
|
||||
)
|
||||
|
||||
assert User.objects.count() == 1
|
||||
|
@ -95,7 +102,6 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
),
|
||||
)
|
||||
|
||||
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||
def test_wrong_auth_user(self):
|
||||
assert User.objects.count() == 0
|
||||
assert AccessLog.objects.count() == 0
|
||||
|
@ -107,6 +113,7 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
HTTP_REMOTE_USER='test',
|
||||
HTTP_AUTH_USER='foobar', # <<< wrong user name
|
||||
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||
secure=True,
|
||||
)
|
||||
|
||||
assert User.objects.count() == 1
|
||||
|
@ -120,7 +127,6 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
|
||||
assert response.status_code == 403 # Forbidden
|
||||
|
||||
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||
def test_wrong_cookie(self):
|
||||
assert User.objects.count() == 0
|
||||
assert AccessLog.objects.count() == 0
|
||||
|
@ -132,6 +138,7 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
HTTP_REMOTE_USER='test',
|
||||
HTTP_AUTH_USER='test',
|
||||
HTTP_AUTHORIZATION='basic dGVzdDp0ZXN0MTIz',
|
||||
secure=True,
|
||||
)
|
||||
|
||||
assert User.objects.count() == 1
|
||||
|
@ -145,7 +152,6 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
|
||||
assert response.status_code == 403 # Forbidden
|
||||
|
||||
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||
def test_wrong_authorization_user(self):
|
||||
assert User.objects.count() == 0
|
||||
|
||||
|
@ -155,7 +161,11 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase):
|
|||
path='/app_path/',
|
||||
HTTP_REMOTE_USER='test',
|
||||
HTTP_AUTH_USER='test',
|
||||
HTTP_AUTHORIZATION=generate_basic_auth(username='foobar', password='test123'), # <<< wrong user name
|
||||
HTTP_AUTHORIZATION=generate_basic_auth(
|
||||
username='foobar', # <<< wrong user name
|
||||
password='test123',
|
||||
),
|
||||
secure=True,
|
||||
)
|
||||
|
||||
assert User.objects.count() == 1
|
||||
|
|
|
@ -4,7 +4,9 @@ import shutil
|
|||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from bx_py_utils.path import assert_is_file
|
||||
from django_tools.serve_media_app.utils import clean_filename
|
||||
from django_tools.unittest_utils.assertments import assert_is_dir, assert_is_file
|
||||
from django_tools.unittest_utils.project_setup import check_editor_config
|
||||
|
||||
import inventory
|
||||
|
||||
|
@ -32,7 +34,7 @@ def poetry_check_output(*args):
|
|||
|
||||
output = subprocess.check_output(
|
||||
(poerty_bin,) + args,
|
||||
universal_newlines=True,
|
||||
text=True,
|
||||
env=os.environ,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=str(PACKAGE_ROOT),
|
||||
|
@ -47,7 +49,7 @@ def test_poetry_check():
|
|||
|
||||
|
||||
def test_requirements_txt():
|
||||
requirements_txt = Path('conf', 'requirements.txt')
|
||||
requirements_txt = PACKAGE_ROOT / 'conf' / 'requirements.txt'
|
||||
assert_is_file(requirements_txt)
|
||||
|
||||
output = poetry_check_output('export', '-f', 'requirements.txt')
|
||||
|
@ -57,8 +59,32 @@ def test_requirements_txt():
|
|||
|
||||
diff = '\n'.join(
|
||||
difflib.unified_diff(
|
||||
current_content.splitlines(), output.splitlines(), fromfile=str(requirements_txt), tofile='FRESH EXPORT'
|
||||
current_content.splitlines(),
|
||||
output.splitlines(),
|
||||
fromfile=str(requirements_txt),
|
||||
tofile='FRESH EXPORT',
|
||||
)
|
||||
)
|
||||
print(diff)
|
||||
assert diff == '', f'{requirements_txt} is not up-to-date! (Hint: call: "make update")'
|
||||
|
||||
|
||||
def test_screenshot_filenames():
|
||||
"""
|
||||
https://forum.yunohost.org/t/yunohost-bot-cant-handle-spaces-in-screenshots/19483
|
||||
"""
|
||||
screenshot_path = PACKAGE_ROOT / 'doc' / 'screenshots'
|
||||
assert_is_dir(screenshot_path)
|
||||
renamed = []
|
||||
for file_path in screenshot_path.iterdir():
|
||||
file_name = file_path.name
|
||||
cleaned_name = clean_filename(file_name)
|
||||
if cleaned_name != file_name:
|
||||
new_path = file_path.with_name(cleaned_name)
|
||||
file_path.rename(new_path)
|
||||
renamed.append(f'{file_name!r} renamed to {cleaned_name!r}')
|
||||
assert not renamed, f'Bad screenshots file names found: {", ".join(renamed)}'
|
||||
|
||||
|
||||
def test_check_editor_config():
|
||||
check_editor_config(package_root=PACKAGE_ROOT)
|
||||
|
|
Loading…
Add table
Reference in a new issue