kopia lustrzana https://github.com/jedie/PyInventory
commit
7c3b6583cb
15
README.md
15
README.md
|
@ -151,14 +151,21 @@ Now, update the containers and copy the files back.
|
|||
Git branches "main" and "deployment" was merged into one.
|
||||
Files are separated into: "/src/" and "/development/"
|
||||
|
||||
### v0.19.0
|
||||
|
||||
Remove ["/development/"](https://github.com/jedie/PyInventory/tree/v0.18.1/deployment) (unmaintained "docker-compose" installation),
|
||||
please use YunoHost ;)
|
||||
|
||||
|
||||
## history
|
||||
|
||||
|
||||
* [**dev**](https://github.com/jedie/PyInventory/compare/v0.18.1...main)
|
||||
* Update to Django 4.2
|
||||
* remove django-processinfo
|
||||
* Bugfix ItemModelAdmin
|
||||
* [**dev**](https://github.com/jedie/PyInventory/compare/v0.19.0...main)
|
||||
* tbc
|
||||
* [v0.19.0 - 15.06.2023](https://github.com/jedie/PyInventory/compare/v0.18.1...v0.19.0)
|
||||
* Update to Django 4.2
|
||||
* remove django-processinfo and "/development/"
|
||||
* Bugfix ItemModelAdmin
|
||||
* [v0.18.1 - 15.06.2023](https://github.com/jedie/PyInventory/compare/v0.18.0...v0.18.1)
|
||||
* Update requirements
|
||||
* [v0.18.0 - 04.04.2023](https://github.com/jedie/PyInventory/compare/v0.17.0...v0.18.0)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
*
|
|
@ -1,20 +0,0 @@
|
|||
.*
|
||||
!.dockerignore
|
||||
!.gitignore
|
||||
|
||||
poetry.lock
|
||||
|
||||
# for django-dbbackup
|
||||
/backups/
|
||||
!/backups/.gitkeep
|
||||
|
||||
# from test projects:
|
||||
/static/
|
||||
/media/
|
||||
*.sqlite3
|
||||
|
||||
# docker-compose usage:
|
||||
volumes
|
||||
|
||||
# Django
|
||||
secret.txt
|
|
@ -1,37 +0,0 @@
|
|||
# https://hub.docker.com/_/python
|
||||
FROM python:3.9-slim-buster
|
||||
|
||||
# for pip cache:
|
||||
ENV XDG_CACHE_HOME=/var/cache
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Install deps
|
||||
RUN set -x \
|
||||
&& apt-get update \
|
||||
&& apt-mark auto $(apt-mark showinstall) \
|
||||
&& apt-get install -y postgresql-client-11 python3-pip \
|
||||
&& apt autoremove \
|
||||
&& apt -y full-upgrade \
|
||||
&& rm -rf /var/lib/apt \
|
||||
&& python3 -m pip install -U pip \
|
||||
&& pip install -U psycopg2-binary
|
||||
|
||||
# Create user for application server:
|
||||
RUN set -x \
|
||||
&& addgroup --system django \
|
||||
&& adduser --system --no-create-home --disabled-password --ingroup django --shell /bin/bash django
|
||||
|
||||
WORKDIR /django
|
||||
|
||||
ARG PROJECT_PACKAGE_NAME
|
||||
ENV PROJECT_PACKAGE_NAME=${PROJECT_PACKAGE_NAME}
|
||||
|
||||
ARG PROJECT_VERSION
|
||||
ENV PROJECT_VERSION=${PROJECT_VERSION}
|
||||
|
||||
# Install project:
|
||||
RUN set -x \
|
||||
&& pip install "${PROJECT_PACKAGE_NAME}>=${PROJECT_VERSION}"
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
SHELL := /bin/bash
|
||||
|
||||
all: help
|
||||
|
||||
help:
|
||||
@echo -e '_________________________________________________________________'
|
||||
@echo -e '*Deployment* Makefile\n'
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9 -_]+:.*?## / {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
check-poetry:
|
||||
@if [[ "$(shell poetry --version 2>/dev/null)" == *"Poetry"* ]] ; \
|
||||
then \
|
||||
echo "Poetry found, ok." ; \
|
||||
else \
|
||||
echo 'Please install poetry first, with e.g.:' ; \
|
||||
echo 'make install-poetry' ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
install-poetry: ## install or update poetry
|
||||
@if [[ "$(shell poetry --version 2>/dev/null)" == *"Poetry"* ]] ; \
|
||||
then \
|
||||
echo 'Update poetry' ; \
|
||||
poetry self update ; \
|
||||
else \
|
||||
echo 'Install poetry' ; \
|
||||
curl -sSL "https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py" | python3 ; \
|
||||
fi
|
||||
|
||||
install: check-poetry ## install requirements to setup project
|
||||
poetry install
|
||||
|
||||
update: check-poetry ## update the sources and docker containers
|
||||
git fetch --all
|
||||
git pull origin master
|
||||
poetry update
|
||||
./compose.sh build --pull
|
||||
$(MAKE) restart
|
||||
|
||||
check-compose:
|
||||
@if [[ "$(shell poetry run docker-compose --version 2>/dev/null)" = *"docker-compose version"* ]] ; \
|
||||
then \
|
||||
echo "docker-compose found, ok." ; \
|
||||
else \
|
||||
echo 'Please install extras first, with e.g.:' ; \
|
||||
echo 'make install-compose' ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
up: check-compose ## Start containers via docker-compose
|
||||
./compose.sh up -d
|
||||
$(MAKE) prune
|
||||
./compose.sh logs --tail=500 --follow
|
||||
|
||||
down: ## Stop all containers
|
||||
./compose.sh down
|
||||
|
||||
prune: ## Cleanup docker
|
||||
docker system prune --force --all --filter until=4464h
|
||||
|
||||
build: check-compose ## Update docker container build
|
||||
./compose.sh pull
|
||||
./compose.sh build --pull
|
||||
|
||||
init_postgres: ## Create postgres database
|
||||
./compose.sh exec postgres ./docker/postgres_init.sh
|
||||
|
||||
##############################################################################
|
||||
|
||||
createsuperuser: ## Create super user
|
||||
./compose.sh exec django ./manage.sh createsuperuser
|
||||
|
||||
##############################################################################
|
||||
|
||||
shell_django: ## Go into bash shell in django container
|
||||
./compose.sh exec django /bin/bash
|
||||
|
||||
shell_postgres: ## Go into bash shell in postgres container
|
||||
./compose.sh exec postgres /bin/bash
|
||||
|
||||
shell_caddy: ## Go into bash shell in caddy container
|
||||
./compose.sh exec caddy /bin/ash
|
||||
|
||||
##############################################################################
|
||||
|
||||
caddy_environ: ## Prints the caddy environment
|
||||
./compose.sh exec caddy /usr/bin/caddy environ
|
||||
|
||||
##############################################################################
|
||||
|
||||
logs: ## Display docker logs from all containers
|
||||
./compose.sh logs --tail=500 --follow
|
||||
|
||||
logs_postgres: ## Display docker logs from postgres container
|
||||
./compose.sh logs --tail=500 --follow postgres
|
||||
|
||||
logs_django: ## Display docker logs from django container
|
||||
./compose.sh logs --tail=500 --follow django
|
||||
|
||||
logs_caddy: ## Display docker logs from caddy container
|
||||
./compose.sh logs --tail=500 --follow caddy
|
||||
|
||||
##############################################################################
|
||||
|
||||
dbbackup: ## Backup database
|
||||
./compose.sh exec django ./manage.sh dbbackup
|
||||
|
||||
dbrestore: ## Restore a database backup
|
||||
./compose.sh exec django ./manage.sh dbrestore
|
||||
|
||||
##############################################################################
|
||||
|
||||
restart: down up ## Restart all containers
|
||||
|
||||
upgrade_django: ## Upgrade "django" container and restart it
|
||||
$(MAKE) build
|
||||
./compose.sh stop django
|
||||
$(MAKE) up
|
||||
|
||||
restart_caddy: ## Restart caddy container
|
||||
./compose.sh stop caddy
|
||||
$(MAKE) up
|
||||
|
||||
##############################################################################
|
||||
|
||||
reload_caddy: ## Reload Caddy server
|
||||
./compose.sh exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||
$(MAKE) logs_caddy
|
||||
|
||||
reload_django: ## Reload server in "django" container
|
||||
./compose.sh exec django /django/reload_gunicorn.sh
|
||||
./compose.sh logs --tail=500 --follow django
|
||||
|
||||
##############################################################################
|
||||
|
||||
.PHONY: help
|
|
@ -1,226 +0,0 @@
|
|||
= PyInventory - deployment instruction
|
||||
|
||||
Install PyInventory on a rood server via docker-compose.
|
||||
|
||||
|
||||
**Note:**
|
||||
|
||||
* PyInventory is also available as [[https://yunohost.org|YunoHost]] App via [[https://github.com/YunoHost-Apps/pyinventory_ynh|pyinventory_ynh]]
|
||||
* This README contains only the instruction to install PyInventory on a root server.
|
||||
* Read [[https://github.com/jedie/PyInventory/tree/master#readme|the main README]] for local development installation.
|
||||
|
||||
|
||||
Pull requests welcome!
|
||||
|
||||
|
||||
== Project structure
|
||||
|
||||
There are two main directories:
|
||||
|
||||
|= directory |= description
|
||||
| **[[https://github.com/jedie/PyInventory/tree/master/src|/src/]]** | The main PyInventory source code
|
||||
| **[[https://github.com/jedie/PyInventory/tree/master/deployment|/deployment/]]** | deploy PyInventory for production use case
|
||||
|
||||
|
||||
== deploy
|
||||
|
||||
Install PyInventory on a root server:
|
||||
|
||||
**Note:**
|
||||
|
||||
* Running a public web server is a lot of work and brings some risks.
|
||||
* This instructions are only the basics to get PyInventory working.
|
||||
* To run the server safely, more work should be done, which is not explained here.
|
||||
* Run at your own risk! No warranty is given.
|
||||
|
||||
|
||||
=== prepare root server
|
||||
|
||||
Here some steps for a fresh created root server:
|
||||
|
||||
Update all packages, e.g.:
|
||||
{{{
|
||||
apt update && apt -y full-upgrade
|
||||
}}}
|
||||
|
||||
Setup a normal user. You may use [[https://github.com/jedie/PyInventory/blob/deployment/scripts/setup_user.sh|scripts/setup_user.sh]]
|
||||
|
||||
|
||||
=== Setup SSH services
|
||||
|
||||
{{{
|
||||
~# nano /etc/ssh/sshd_config
|
||||
}}}
|
||||
|
||||
Change e.g.:
|
||||
{{{
|
||||
Port xxxx
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
}}}
|
||||
(Changing the Port may need to change a firewall/network settings)
|
||||
|
||||
{{{
|
||||
# restart SSH deamon:
|
||||
~# service ssh restart
|
||||
|
||||
# Display and follow the ssh log output to see connection errors:
|
||||
~# journalctl -f -u ssh
|
||||
}}}
|
||||
|
||||
* Keep the current SSH session (with the log output) open!
|
||||
* Update your {{{~/.ssh/config}}}
|
||||
* Try to connect as the new, normal user in a **separate** terminal
|
||||
|
||||
Only after a working new connection: Terminate the first root SSH session ;)
|
||||
|
||||
|
||||
=== setup unattended-upgrades
|
||||
|
||||
{{{
|
||||
~$ sudo apt install unattended-upgrades
|
||||
~$ sudo dpkg-reconfigure unattended-upgrades
|
||||
~$ sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
}}}
|
||||
|
||||
|
||||
=== install requirements
|
||||
|
||||
Install docker, see: https://docs.docker.com/engine/install/ubuntu/
|
||||
|
||||
install some base packages, e.g.:
|
||||
{{{
|
||||
~$ sudo apt install git make
|
||||
}}}
|
||||
|
||||
|
||||
|
||||
=== install PyInventory
|
||||
|
||||
{{{
|
||||
# Checkout the deployment branch:
|
||||
~$ git clone https://github.com/jedie/PyInventory.git
|
||||
~$ cd PyInventory/deployment/
|
||||
|
||||
# Theses Makefile targets exists:
|
||||
~/PyInventory/deployment$ make
|
||||
_________________________________________________________________
|
||||
*Deployment* Makefile
|
||||
|
||||
install-poetry install or update poetry
|
||||
install install requirements to setup project
|
||||
update update the sources and docker containers
|
||||
up Start containers via docker-compose
|
||||
down Stop all containers
|
||||
prune Cleanup docker
|
||||
build Update docker container build
|
||||
init_postgres Create postgres database
|
||||
createsuperuser Create super user
|
||||
shell_django Go into bash shell in django container
|
||||
shell_postgres Go into bash shell in postgres container
|
||||
shell_caddy Go into bash shell in caddy container
|
||||
caddy_environ Prints the caddy environment
|
||||
logs Display docker logs from all containers
|
||||
logs_postgres Display docker logs from postgres container
|
||||
logs_django Display docker logs from django container
|
||||
logs_caddy Display docker logs from caddy container
|
||||
dbbackup Backup database
|
||||
dbrestore Restore a database backup
|
||||
restart Restart all containers
|
||||
upgrade_django Upgrade "django" container and restart it
|
||||
restart_caddy Restart caddy container
|
||||
reload_caddy Reload Caddy server
|
||||
reload_django Reload server in "django" container
|
||||
}}}
|
||||
|
||||
Install, e.g.:
|
||||
|
||||
{{{
|
||||
# install or update poetry:
|
||||
~/PyInventory/deployment$ make install-poetry
|
||||
}}}
|
||||
|
||||
To keep poetry running (PATH must be expand) just logout and login ;)
|
||||
|
||||
{{{
|
||||
# install requirements (e.g.: docker-compose) via poetry:
|
||||
~/PyInventory/deployment$ make install
|
||||
}}}
|
||||
|
||||
Create a {{{.env}}} file in project root directory with these content, e.g.:
|
||||
{{{
|
||||
~/PyInventory/deployment$ touch .env
|
||||
~/PyInventory/deployment$ nano .env
|
||||
~/PyInventory/deployment$ cat .env
|
||||
# Your Public domain:
|
||||
HOSTNAME=domain.tld
|
||||
|
||||
# eMail address for Let's encrypt:
|
||||
LETSENCRYPT_EMAIL=webmaster@domain.tld
|
||||
}}}
|
||||
|
||||
For local testing of the docker-compose setup, used this values:
|
||||
{{{
|
||||
HOSTNAME=localhost
|
||||
LETSENCRYPT_EMAIL=internal
|
||||
}}}
|
||||
(Caddy will create a self signed https certificate)
|
||||
|
||||
Start containers via docker-compose:
|
||||
{{{
|
||||
~/PyInventory/deployment$ make up
|
||||
}}}
|
||||
|
||||
Notes: At the first start it takes a little while until the database is created ;)
|
||||
|
||||
Create first super user:
|
||||
{{{
|
||||
~/PyInventory/deployment$ make docker_createsuperuser
|
||||
}}}
|
||||
|
||||
* Now you should be able to connect to your PyInventory installation and login with created super user.
|
||||
* Redirect from **http** to **https** should work.
|
||||
* Let's Encrypt certificate should be installed and valid.
|
||||
* Containers should be restarted after a server reboot
|
||||
|
||||
|
||||
=== Maintenance
|
||||
|
||||
TO keep everything up-to-date do the following steps:
|
||||
|
||||
Update the OS call:
|
||||
{{{
|
||||
~/PyInventory/deployment$ sudo ./scripts/apt-distupgrade.sh
|
||||
}}}
|
||||
|
||||
Update PyInventory installation and docker containers:
|
||||
{{{
|
||||
~/PyInventory/deployment$ make update
|
||||
}}}
|
||||
|
||||
This will do:
|
||||
|
||||
* update the source code
|
||||
* update docker-compose and all requirements
|
||||
* Pull and rebuild all docker containers
|
||||
* restart all docker containers
|
||||
|
||||
Take a look at [[https://github.com/jedie/PyInventory/blob/deployment/scripts/apt-cleanup.sh|scripts/apt-cleanup.sh]] to keep your system clean.
|
||||
|
||||
|
||||
== links ==
|
||||
|
||||
| Homepage | http://github.com/jedie/PyInventory
|
||||
|
||||
Web server stuff:
|
||||
|
||||
* https://help.ubuntu.com/community/Security
|
||||
* https://help.ubuntu.com/lts/serverguide/automatic-updates.html
|
||||
* https://help.ubuntu.com/community/AutomaticSecurityUpdate
|
||||
|
||||
|
||||
== donation ==
|
||||
|
||||
* [[https://www.paypal.me/JensDiemer|paypal.me/JensDiemer]]
|
||||
* [[https://flattr.com/submit/auto?uid=jedie&url=https%3A%2F%2Fgithub.com%2Fjedie%2FPyInventory%2F|Flattr This!]]
|
||||
* Send [[http://www.bitcoin.org/|Bitcoins]] to [[https://blockexplorer.com/address/1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F|1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F]]
|
|
@ -1,28 +0,0 @@
|
|||
# https://caddyserver.com/docs/caddyfile
|
||||
|
||||
{$HOSTNAME} {
|
||||
tls {$LETSENCRYPT_EMAIL}
|
||||
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
level WARN
|
||||
}
|
||||
|
||||
header {
|
||||
X-Robots-Tag "none"
|
||||
}
|
||||
|
||||
respond /robots.txt 200 {
|
||||
body "User-agent: *
|
||||
Disallow: /"
|
||||
close
|
||||
}
|
||||
|
||||
route {
|
||||
file_server /static/* {
|
||||
root /srv/
|
||||
}
|
||||
reverse_proxy django:8000
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
DB_USER=postgres
|
||||
DB_PASS=postgres
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -f .env ]]; then
|
||||
echo "Read '.env' file..."
|
||||
source .env
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
source project.env
|
||||
exec poetry run docker-compose -f docker-compose.yml -f docker-compose.dev.yml "$@"
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -f .env ]]; then
|
||||
echo "Read '.env' file..."
|
||||
source .env
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
source project.env
|
||||
exec poetry run docker-compose "$@"
|
|
@ -1,43 +0,0 @@
|
|||
"""
|
||||
Django settings for docker usage
|
||||
"""
|
||||
import os as __os
|
||||
|
||||
from inventory_project.settings.base import * # noqa
|
||||
|
||||
|
||||
HOSTNAME = __os.environ['HOSTNAME']
|
||||
|
||||
|
||||
if HOSTNAME != 'localhost':
|
||||
print(f'Production mode on domain: {HOSTNAME!r}')
|
||||
DEBUG = False
|
||||
INTERNAL_IPS = ()
|
||||
else:
|
||||
print('Local development mode')
|
||||
DEBUG = True
|
||||
INTERNAL_IPS = ('127.0.0.1', '0.0.0.0', 'localhost')
|
||||
|
||||
|
||||
SERVE_FILES = False # Caddy serve static/media files
|
||||
|
||||
|
||||
ALLOWED_HOSTS = (HOSTNAME,)
|
||||
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': __os.environ['DB_NAME'],
|
||||
'USER': __os.environ['DB_USER'],
|
||||
'PASSWORD': __os.environ['DB_PASS'],
|
||||
'HOST': __os.environ['DB_HOST'],
|
||||
'PORT': __os.environ['DB_PORT'],
|
||||
'DEBUG_NAME': 'default',
|
||||
'CONN_MAX_AGE': 600,
|
||||
},
|
||||
}
|
||||
|
||||
# docker volumes:
|
||||
STATIC_ROOT = '/static/'
|
||||
MEDIA_ROOT = '/media/'
|
|
@ -1,46 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
restart_error_handler() {
|
||||
(
|
||||
echo "Restart ${0} in 3 sec..."
|
||||
sleep 1
|
||||
echo "Restart ${0} in 2 sec..."
|
||||
sleep 1
|
||||
echo "Restart ${0} in 1 sec..."
|
||||
sleep 1
|
||||
)
|
||||
exec ${0}
|
||||
}
|
||||
trap restart_error_handler 0
|
||||
|
||||
echo "_______________________________________________________________________"
|
||||
echo "$(date +%c) - ${0}"
|
||||
|
||||
if [ -d "/dist/" ] ; then
|
||||
(
|
||||
set -x
|
||||
pip3 install -U /dist/*.whl
|
||||
)
|
||||
else
|
||||
(
|
||||
set -x
|
||||
pip3 install -U "${PROJECT_PACKAGE_NAME}>=${PROJECT_VERSION}"
|
||||
)
|
||||
fi
|
||||
|
||||
(
|
||||
set -x
|
||||
|
||||
./manage.py collectstatic --noinput
|
||||
./manage.py migrate
|
||||
|
||||
su django -c "/usr/local/bin/gunicorn --config /django/gunicorn.conf.py wsgi"
|
||||
|
||||
echo "gunicorn terminated with exit code: $?"
|
||||
sleep 3
|
||||
exit 1
|
||||
)
|
||||
|
||||
exit 2
|
|
@ -1,18 +0,0 @@
|
|||
"""
|
||||
Configuration for Gunicorn
|
||||
"""
|
||||
import multiprocessing
|
||||
|
||||
|
||||
bind = 'django:8000'
|
||||
|
||||
# https://docs.gunicorn.org/en/latest/settings.html#workers
|
||||
workers = multiprocessing.cpu_count() * 2 + 1
|
||||
|
||||
# https://docs.gunicorn.org/en/latest/settings.html#logging
|
||||
loglevel = 'info'
|
||||
accesslog = '-' # log to stdout
|
||||
errorlog = '-' # log to stdout
|
||||
|
||||
# https://docs.gunicorn.org/en/latest/settings.html#pidfile
|
||||
pidfile = '/tmp/gunicorn.pid'
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
assert 'DJANGO_SETTINGS_MODULE' in os.environ, 'No "DJANGO_SETTINGS_MODULE" in environment!'
|
||||
from django.core.management import execute_from_command_line
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
for pid in $(cat /tmp/gunicorn.pid); do kill $pid; done
|
|
@ -1,9 +0,0 @@
|
|||
"""
|
||||
WSGI config
|
||||
"""
|
||||
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
|
||||
application = get_wsgi_application()
|
|
@ -1,14 +0,0 @@
|
|||
version: "3.7"
|
||||
|
||||
services:
|
||||
caddy: # https://hub.docker.com/_/caddy
|
||||
environment:
|
||||
- HOSTNAME=localhost
|
||||
- LETSENCRYPT_EMAIL=internal
|
||||
|
||||
django:
|
||||
environment:
|
||||
- DJANGO_SETTINGS_MODULE=docker_settings
|
||||
- HOSTNAME=localhost
|
||||
volumes:
|
||||
- ./dist/:/dist/
|
|
@ -1,65 +0,0 @@
|
|||
version: "3.7"
|
||||
|
||||
services:
|
||||
caddy: # https://hub.docker.com/_/caddy
|
||||
image: caddy:2-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- ./volumes/caddy/data/:/data/:rw
|
||||
- ./volumes/caddy/config/:/config/:rw
|
||||
# Servce django static files with caddy:
|
||||
- ./volumes/django/static/:/srv/static/:ro
|
||||
environment:
|
||||
- HOSTNAME=${HOSTNAME:-localhost}
|
||||
- LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL:-internal}
|
||||
|
||||
django:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- PROJECT_PACKAGE_NAME=${PROJECT_PACKAGE_NAME}
|
||||
- PROJECT_VERSION=${PROJECT_VERSION}
|
||||
restart: unless-stopped
|
||||
hostname: django
|
||||
ports:
|
||||
- "8000"
|
||||
env_file: ./common.env
|
||||
environment:
|
||||
- DJANGO_SETTINGS_MODULE=docker_settings
|
||||
- HOSTNAME=${HOSTNAME:-localhost}
|
||||
- DB_NAME=${PROJECT_NAME}
|
||||
links:
|
||||
- postgres:postgres
|
||||
depends_on:
|
||||
- postgres
|
||||
- caddy
|
||||
volumes:
|
||||
- ./django/:/django/:ro
|
||||
- ./volumes/django/:/django_volumes/:rw
|
||||
# static files, served by caddy:
|
||||
- ./volumes/django/static/:/static/:rw
|
||||
# Use files, served by django:
|
||||
- ./volumes/django/media/:/media/:rw
|
||||
# e.g.: pip cache must be the same value as $XDG_CACHE_HOME !
|
||||
- ./volumes/cache/:/var/cache/:rw
|
||||
entrypoint: /django/entrypoint.sh
|
||||
|
||||
postgres:
|
||||
# https://hub.docker.com/_/postgres
|
||||
image: postgres:11-alpine
|
||||
restart: unless-stopped
|
||||
hostname: postgres
|
||||
ports:
|
||||
- "5432"
|
||||
env_file: ./common.env
|
||||
environment:
|
||||
- DB_NAME=${PROJECT_NAME}
|
||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
volumes:
|
||||
- ./postgres/init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh:ro
|
||||
- ./volumes/postgresql/data/:/var/lib/postgresql/data/:rw
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
psql -U postgres -c "CREATE DATABASE \"$DB_NAME\" OWNER \"$DB_USER\""
|
|
@ -1,3 +0,0 @@
|
|||
export PROJECT_NAME=pyinventory
|
||||
export PROJECT_PACKAGE_NAME=pyinventory
|
||||
export PROJECT_VERSION=0.18.1
|
|
@ -1,16 +0,0 @@
|
|||
[tool.poetry]
|
||||
name = "pyinventory-deployment"
|
||||
version = "0.1.0"
|
||||
description = "production deployment for PyInventory project with docker-compose usage"
|
||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
||||
license = "GPL"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.7,<4.0.0"
|
||||
docker-compose = "*"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
|
@ -1,69 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Cleanup installed packages by using apt-mark:
|
||||
#
|
||||
# 1. mark all packages as "auto"
|
||||
# 2. install really needed packages "manual"
|
||||
# 3. call "autoremove" to deinstall all not needed packages
|
||||
#
|
||||
# WARNING: You may need some more packages depend on your cloud provider!
|
||||
|
||||
|
||||
|
||||
###############################################################
|
||||
# Remove this lines:
|
||||
echo "Adjust this script first, before you use it!"
|
||||
exit 1
|
||||
###############################################################
|
||||
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(whoami)" != "root" ]; then
|
||||
echo "Please start with 'sudo' !"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
# These packages should be installed:
|
||||
PACKAGES=(
|
||||
linux-image-virtual ubuntu-minimal acpid
|
||||
qemu-guest-agent
|
||||
command-not-found
|
||||
update-manager-core
|
||||
unattended-upgrades
|
||||
openssh-server
|
||||
rsync
|
||||
lshw htop mc nano
|
||||
git make
|
||||
apt-transport-https curl gnupg-agent software-properties-common
|
||||
docker-ce docker-ce-cli containerd.io
|
||||
)
|
||||
|
||||
(
|
||||
set -ex
|
||||
|
||||
apt update
|
||||
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
|
||||
# Mark all installed packages as "auto":
|
||||
apt-mark auto $(apt-mark showinstall)
|
||||
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
|
||||
# Install the really needed packages:
|
||||
apt -y install "${PACKAGES[@]}"
|
||||
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
|
||||
# Update all installed packages:
|
||||
apt -y full-upgrade
|
||||
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
|
||||
# Deinstall all not needed packages:
|
||||
apt autoremove
|
||||
)
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
(
|
||||
set -x
|
||||
sudo apt update
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
sudo apt -y full-upgrade
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
sudo apt -y autoremove
|
||||
{ echo "---------------------------------------------------"; } 2>/dev/null
|
||||
# Delete old entries:
|
||||
sudo journalctl --vacuum-size=1G
|
||||
sudo journalctl --vacuum-time=1years
|
||||
)
|
|
@ -1,21 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$(whoami)" != "root" ]; then
|
||||
echo "Please start with 'sudo' !"
|
||||
(
|
||||
set -x
|
||||
id
|
||||
exit 1
|
||||
)
|
||||
fi
|
||||
|
||||
|
||||
set -ex
|
||||
|
||||
export USERNAME=${1}
|
||||
|
||||
adduser --disabled-password --gecos "" --home=/home/${USERNAME} ${USERNAME}
|
||||
mkdir -p /home/${USERNAME}/.ssh
|
||||
cp /root/.ssh/authorized_keys /home/${USERNAME}/.ssh/
|
||||
chown -Rfc ${USERNAME}.${USERNAME} /home/${USERNAME}/
|
||||
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL">/etc/sudoers.d/${USERNAME}
|
|
@ -46,40 +46,6 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-
|
|||
tests = ["attrs[tests-no-zope]", "zope-interface"]
|
||||
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "4.0.1"
|
||||
description = "Modern password hashing for your software and your servers"
|
||||
optional = true
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"},
|
||||
{file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"},
|
||||
{file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"},
|
||||
{file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"},
|
||||
{file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"},
|
||||
{file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"},
|
||||
{file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"},
|
||||
{file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"},
|
||||
{file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"},
|
||||
{file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"},
|
||||
{file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"},
|
||||
{file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
tests = ["pytest (>=3.2.1,!=3.3.0)"]
|
||||
typecheck = ["mypy"]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.12.2"
|
||||
|
@ -669,17 +635,6 @@ files = [
|
|||
{file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distro"
|
||||
version = "1.8.0"
|
||||
description = "Distro - an OS platform information API"
|
||||
optional = true
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "distro-1.8.0-py3-none-any.whl", hash = "sha256:99522ca3e365cac527b44bde033f64c6945d90eb9f769703caaec52b09bbd3ff"},
|
||||
{file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "4.2.3"
|
||||
|
@ -878,69 +833,6 @@ django = "*"
|
|||
icdiff = "*"
|
||||
pprintpp = "*"
|
||||
|
||||
[[package]]
|
||||
name = "docker"
|
||||
version = "6.1.3"
|
||||
description = "A Python library for the Docker Engine API."
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"},
|
||||
{file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
packaging = ">=14.0"
|
||||
paramiko = {version = ">=2.4.3", optional = true, markers = "extra == \"ssh\""}
|
||||
pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""}
|
||||
requests = ">=2.26.0"
|
||||
urllib3 = ">=1.26.0"
|
||||
websocket-client = ">=0.32.0"
|
||||
|
||||
[package.extras]
|
||||
ssh = ["paramiko (>=2.4.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "docker-compose"
|
||||
version = "1.29.2"
|
||||
description = "Multi-container orchestration for Docker"
|
||||
optional = true
|
||||
python-versions = ">=3.4"
|
||||
files = [
|
||||
{file = "docker-compose-1.29.2.tar.gz", hash = "sha256:4c8cd9d21d237412793d18bd33110049ee9af8dab3fe2c213bbd0733959b09b7"},
|
||||
{file = "docker_compose-1.29.2-py2.py3-none-any.whl", hash = "sha256:8d5589373b35c8d3b1c8c1182c6e4a4ff14bffa3dd0b605fcd08f73c94cef809"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = ">=0.4,<1", markers = "sys_platform == \"win32\""}
|
||||
distro = ">=1.5.0,<2"
|
||||
docker = {version = ">=5", extras = ["ssh"]}
|
||||
dockerpty = ">=0.4.1,<1"
|
||||
docopt = ">=0.6.1,<1"
|
||||
jsonschema = ">=2.5.1,<4"
|
||||
python-dotenv = ">=0.13.0,<1"
|
||||
PyYAML = ">=3.10,<6"
|
||||
requests = ">=2.20.0,<3"
|
||||
texttable = ">=0.9.0,<2"
|
||||
websocket-client = ">=0.32.0,<1"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2)"]
|
||||
tests = ["ddt (>=1.2.2,<2)", "pytest (<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "dockerpty"
|
||||
version = "0.4.1"
|
||||
description = "Python library to use the pseudo-tty of a docker container"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "dockerpty-0.4.1.tar.gz", hash = "sha256:69a9d69d573a0daa31bcd1c0774eeed5c15c295fe719c61aca550ed1393156ce"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
six = ">=1.3.0"
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.6.2"
|
||||
|
@ -1296,27 +1188,6 @@ files = [
|
|||
test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"]
|
||||
trio = ["async_generator", "trio"]
|
||||
|
||||
[[package]]
|
||||
name = "jsonschema"
|
||||
version = "3.2.0"
|
||||
description = "An implementation of JSON Schema validation for Python"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"},
|
||||
{file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=17.4.0"
|
||||
pyrsistent = ">=0.14.0"
|
||||
setuptools = "*"
|
||||
six = ">=1.11.0"
|
||||
|
||||
[package.extras]
|
||||
format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"]
|
||||
format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"]
|
||||
|
||||
[[package]]
|
||||
name = "keyring"
|
||||
version = "24.2.0"
|
||||
|
@ -1621,27 +1492,6 @@ files = [
|
|||
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paramiko"
|
||||
version = "3.2.0"
|
||||
description = "SSH2 protocol library"
|
||||
optional = true
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "paramiko-3.2.0-py3-none-any.whl", hash = "sha256:df0f9dd8903bc50f2e10580af687f3015bf592a377cd438d2ec9546467a14eb8"},
|
||||
{file = "paramiko-3.2.0.tar.gz", hash = "sha256:93cdce625a8a1dc12204439d45033f3261bdb2c201648cfcdc06f9fd0f94ec29"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
bcrypt = ">=3.2"
|
||||
cryptography = ">=3.3"
|
||||
pynacl = ">=1.5"
|
||||
|
||||
[package.extras]
|
||||
all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
|
||||
gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
|
||||
invoke = ["invoke (>=2.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.11.1"
|
||||
|
@ -1966,32 +1816,6 @@ files = [
|
|||
[package.extras]
|
||||
plugins = ["importlib-metadata"]
|
||||
|
||||
[[package]]
|
||||
name = "pynacl"
|
||||
version = "1.5.0"
|
||||
description = "Python binding to the Networking and Cryptography (NaCl) library"
|
||||
optional = true
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"},
|
||||
{file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"},
|
||||
{file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cffi = ">=1.4.1"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
||||
tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyperclip"
|
||||
version = "1.8.2"
|
||||
|
@ -2032,42 +1856,6 @@ files = [
|
|||
{file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyrsistent"
|
||||
version = "0.19.3"
|
||||
description = "Persistent/Functional/Immutable data structures"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"},
|
||||
{file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"},
|
||||
{file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"},
|
||||
{file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"},
|
||||
{file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"},
|
||||
{file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"},
|
||||
{file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"},
|
||||
{file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"},
|
||||
{file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"},
|
||||
{file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"},
|
||||
{file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"},
|
||||
{file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"},
|
||||
{file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"},
|
||||
{file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"},
|
||||
{file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"},
|
||||
{file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"},
|
||||
{file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"},
|
||||
{file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"},
|
||||
{file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"},
|
||||
{file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"},
|
||||
{file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"},
|
||||
{file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"},
|
||||
{file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"},
|
||||
{file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"},
|
||||
{file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"},
|
||||
{file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"},
|
||||
{file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.0"
|
||||
|
@ -2187,20 +1975,6 @@ files = [
|
|||
[package.dependencies]
|
||||
docutils = "*"
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "0.21.1"
|
||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"},
|
||||
{file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "python-slugify"
|
||||
version = "8.0.1"
|
||||
|
@ -2259,29 +2033,6 @@ files = [
|
|||
[package.dependencies]
|
||||
tokenize-rt = ">=3.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "pywin32"
|
||||
version = "306"
|
||||
description = "Python for Window Extensions"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
|
||||
{file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
|
||||
{file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
|
||||
{file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
|
||||
{file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
|
||||
{file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
|
||||
{file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
|
||||
{file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
|
||||
{file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
|
||||
{file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
|
||||
{file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
|
||||
{file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
|
||||
{file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
|
||||
{file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pywin32-ctypes"
|
||||
version = "0.2.2"
|
||||
|
@ -2295,40 +2046,51 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "5.4.1"
|
||||
version = "6.0.1"
|
||||
description = "YAML parser and emitter for Python"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
|
||||
{file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"},
|
||||
{file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"},
|
||||
{file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
|
||||
{file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
|
||||
{file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
|
||||
{file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
|
||||
{file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
|
||||
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2632,17 +2394,6 @@ files = [
|
|||
{file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "texttable"
|
||||
version = "1.6.7"
|
||||
description = "module to create simple ASCII tables"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"},
|
||||
{file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokenize-rt"
|
||||
version = "5.1.0"
|
||||
|
@ -2806,20 +2557,6 @@ files = [
|
|||
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websocket-client"
|
||||
version = "0.59.0"
|
||||
description = "WebSocket client for Python with low level API options"
|
||||
optional = true
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
files = [
|
||||
{file = "websocket-client-0.59.0.tar.gz", hash = "sha256:d376bd60eace9d437ab6d7ee16f4ab4e821c9dae591e1b783c58ebd8aaf80c5c"},
|
||||
{file = "websocket_client-0.59.0-py2.py3-none-any.whl", hash = "sha256:2e50d26ca593f70aba7b13a489435ef88b8fc3b5c5643c1ce8808ff9b40f0b32"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "xlrd"
|
||||
version = "2.0.1"
|
||||
|
@ -2869,4 +2606,4 @@ psycopg2-source = ["psycopg2"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9,<4.0.0"
|
||||
content-hash = "c1cc7b68e0d4fdc3ebfb977fd4dc524e5b04cf86e744a9c8ddaa2cefa6b9d9a5"
|
||||
content-hash = "84cfc2d59afa7c8f9a4eae92caaef1091159ec3f7c58a0ee3e73656fcf633217"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "PyInventory"
|
||||
version = "0.18.1"
|
||||
version = "0.19.0"
|
||||
description = "Web based management to catalog things including state and location etc. using Python/Django."
|
||||
authors = [
|
||||
"Jens Diemer <PyInventory@jensdiemer.de>",
|
||||
|
@ -59,8 +59,6 @@ django-axes = "*" # https://github.com/jazzband/django-axes
|
|||
requests = "*" # https://github.com/psf/requests
|
||||
pillow = "*"
|
||||
|
||||
docker-compose = { version = "*", optional = true } # install via: poetry install --extras "docker"
|
||||
|
||||
psycopg2-binary = { version = "*", optional = true } # install via: poetry install --extras "postgres-binary"
|
||||
psycopg2 = { version = "*", optional = true } # install via: poetry install --extras "psycopg2-source"
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ from bx_django_utils.test_utils.html_assertion import HtmlAssertionMixin, assert
|
|||
from django.template.defaulttags import CsrfTokenNode, NowNode
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
from inventory import __version__
|
||||
from inventory_project.tests.fixtures import get_normal_user
|
||||
from inventory_project.tests.mocks import MockInventoryVersionString
|
||||
|
||||
|
||||
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||
|
@ -18,7 +18,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
self.client.force_login(self.normaluser)
|
||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
||||
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||
):
|
||||
), MockInventoryVersionString():
|
||||
response = self.client.get(
|
||||
path='/admin/inventory/locationmodel/',
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
self.assert_html_parts(
|
||||
response,
|
||||
parts=(
|
||||
f'<title>Select Location to change | PyInventory v{__version__}</title>',
|
||||
'<title>Select Location to change | PyInventory vMockedVersionString</title>',
|
||||
'<a href="/admin/inventory/locationmodel/add/" class="addlink">Add Location</a>',
|
||||
'<p class="paginator">0 Locations</p>',
|
||||
),
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
from unittest import mock
|
||||
|
||||
from bx_py_utils.test_utils.context_managers import MassContextManager
|
||||
|
||||
from inventory import context_processors
|
||||
|
||||
|
||||
class MockInventoryVersionString(MassContextManager):
|
||||
def __init__(self):
|
||||
self.mocks = [
|
||||
mock.patch.object(context_processors, '__version__', self),
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
return 'MockedVersionString'
|
|
@ -10,16 +10,15 @@ from django.utils import timezone
|
|||
from django_tools.unittest_utils.mockup import ImageDummy
|
||||
from reversion.models import Revision
|
||||
|
||||
from inventory import __version__
|
||||
from inventory.models import ItemImageModel, ItemModel
|
||||
from inventory_project.tests.fixtures import get_normal_user
|
||||
from inventory_project.tests.mocks import MockInventoryVersionString
|
||||
|
||||
|
||||
ITEM_FORM_DEFAULTS = {
|
||||
'version': 0, # VersionProtectBaseModel field
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '0',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
|
@ -55,27 +54,22 @@ class AdminAnonymousTests(HtmlAssertionMixin, TestCase):
|
|||
fetch_redirect_response=False
|
||||
)
|
||||
|
||||
response = self.client.get(
|
||||
path='/admin/inventory/itemmodel/add/',
|
||||
secure=True,
|
||||
HTTP_ACCEPT_LANGUAGE='en'
|
||||
)
|
||||
response = self.client.get(path='/admin/inventory/itemmodel/add/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
||||
self.assertRedirects(
|
||||
response,
|
||||
expected_url='/admin/login/?next=/admin/inventory/itemmodel/add/',
|
||||
fetch_redirect_response=False
|
||||
response, expected_url='/admin/login/?next=/admin/inventory/itemmodel/add/', fetch_redirect_response=False
|
||||
)
|
||||
with mock.patch.object(CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'):
|
||||
response = self.client.get(
|
||||
path='/admin/login/',
|
||||
secure=True,
|
||||
HTTP_ACCEPT_LANGUAGE='en'
|
||||
with mock.patch.object(
|
||||
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||
), MockInventoryVersionString():
|
||||
response = self.client.get(path='/admin/login/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
||||
self.assert_html_parts(
|
||||
response,
|
||||
parts=(
|
||||
'<title>Log in | PyInventory vMockedVersionString</title>',
|
||||
'<label class="required" for="id_username">Username:</label>',
|
||||
'<label class="required" for="id_password">Password:</label>',
|
||||
),
|
||||
)
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Log in | PyInventory v{__version__}</title>',
|
||||
'<label class="required" for="id_username">Username:</label>',
|
||||
'<label class="required" for="id_password">Password:</label>',
|
||||
))
|
||||
assert_html_response_snapshot(response, validate=False)
|
||||
|
||||
|
||||
|
@ -87,16 +81,16 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
|
||||
def test_normal_user_create_minimal_item(self):
|
||||
offset = datetime.timedelta(minutes=1)
|
||||
with mock.patch.object(timezone, 'now', MockDatetimeGenerator(offset=offset)),\
|
||||
mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), \
|
||||
mock.patch.object(CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'):
|
||||
with mock.patch.object(timezone, 'now', MockDatetimeGenerator(offset=offset)), mock.patch.object(
|
||||
NowNode, 'render', return_value='MockedNowNode'
|
||||
), mock.patch.object(
|
||||
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||
), MockInventoryVersionString():
|
||||
self.client.force_login(self.normaluser)
|
||||
|
||||
response = self.client.get('/admin/inventory/itemmodel/add/')
|
||||
assert response.status_code == 200
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Add Item | PyInventory v{__version__}</title>',
|
||||
))
|
||||
self.assert_html_parts(response, parts=('<title>Add Item | PyInventory vMockedVersionString</title>',))
|
||||
assert_html_response_snapshot(response=response, validate=False)
|
||||
|
||||
assert ItemModel.objects.count() == 0
|
||||
|
@ -133,11 +127,14 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
path=f'/admin/inventory/itemmodel/{item.pk}/change/',
|
||||
data=post_data,
|
||||
)
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Change Item | PyInventory v{__version__}</title>',
|
||||
'<li>Version error: Overwrite version 2 with 1 is forbidden!</li>',
|
||||
'<pre>- "name"\n+ "A new Name!"</pre>'
|
||||
))
|
||||
self.assert_html_parts(
|
||||
response,
|
||||
parts=(
|
||||
'<title>Change Item | PyInventory vMockedVersionString</title>',
|
||||
'<li>Version error: Overwrite version 2 with 1 is forbidden!</li>',
|
||||
'<pre>- "name"\n+ "A new Name!"</pre>',
|
||||
),
|
||||
)
|
||||
html = response.content.decode('utf-8')
|
||||
html = html.replace(str(item.pk), '<removed-UUID>')
|
||||
assert_html_snapshot(got=html, validate=False)
|
||||
|
@ -217,7 +214,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
|
||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
||||
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||
):
|
||||
), MockInventoryVersionString():
|
||||
response = self.client.get(
|
||||
path='/admin/inventory/itemmodel/',
|
||||
)
|
||||
|
@ -225,7 +222,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
self.assert_html_parts(
|
||||
response,
|
||||
parts=(
|
||||
f'<title>Select Item to change | PyInventory v{__version__}</title>',
|
||||
'<title>Select Item to change | PyInventory vMockedVersionString</title>',
|
||||
'<a href="/admin/inventory/itemmodel/00000000-0001-0000-0000-000000000000/change/">'
|
||||
'<strong>main item 1</strong></a>',
|
||||
'<a href="/admin/inventory/itemmodel/00000000-0001-0001-0000-000000000000/change/">'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html dir="ltr" lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Change Item | PyInventory v0.18.1
|
||||
Change Item | PyInventory vMockedVersionString
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet"/>
|
||||
<link href="/static/admin/css/dark_mode.css" rel="stylesheet"/>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.18.1
|
||||
PyInventory vMockedVersionString
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
|
|
@ -8,9 +8,9 @@ from django_tools.unittest_utils.mockup import ImageDummy
|
|||
from model_bakery import baker
|
||||
from reversion.models import Revision
|
||||
|
||||
from inventory import __version__
|
||||
from inventory.models import MemoImageModel, MemoModel
|
||||
from inventory.permissions import get_or_create_normal_user_group
|
||||
from inventory_project.tests.mocks import MockInventoryVersionString
|
||||
|
||||
|
||||
class AdminAnonymousTests(TestCase):
|
||||
|
@ -42,13 +42,12 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
def test_normal_user_create_minimal_item(self):
|
||||
self.client.force_login(self.normaluser)
|
||||
|
||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), \
|
||||
mock.patch.object(CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'):
|
||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
||||
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||
), MockInventoryVersionString():
|
||||
response = self.client.get('/admin/inventory/memomodel/add/')
|
||||
assert response.status_code == 200
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Add Memo | PyInventory v{__version__}</title>',
|
||||
))
|
||||
self.assert_html_parts(response, parts=('<title>Add Memo | PyInventory vMockedVersionString</title>',))
|
||||
assert_html_response_snapshot(response=response, validate=False)
|
||||
|
||||
assert MemoModel.objects.count() == 0
|
||||
|
|
|
@ -46,11 +46,6 @@ def test_version(package_root=None, version=None):
|
|||
string=f'version = "{version}"'
|
||||
)
|
||||
|
||||
assert_file_contains_string(
|
||||
file_path=Path(package_root, 'deployment', 'project.env'),
|
||||
string=f'PROJECT_VERSION={version}'
|
||||
)
|
||||
|
||||
|
||||
def test_poetry_check(package_root=None):
|
||||
if package_root is None:
|
||||
|
|
Ładowanie…
Reference in New Issue