Compare commits
43 commits
Author | SHA1 | Date | |
---|---|---|---|
Jan Dittberner | 998c3d220f | ||
Jan Dittberner | f524c08eff | ||
Jan Dittberner | afae6411c7 | ||
Jan Dittberner | a684139749 | ||
Jan Dittberner | e197413127 | ||
Jan Dittberner | 46e3db3a89 | ||
Jan Dittberner | a04d5b754f | ||
Jan Dittberner | f97fb6f700 | ||
Jan Dittberner | f999e65a10 | ||
Jan Dittberner | 8898c1506e | ||
Jan Dittberner | 94705f26bd | ||
Jan Dittberner | 7911df39fa | ||
Jan Dittberner | 4ad9b32f7e | ||
Jan Dittberner | c4e7e8c497 | ||
Jan Dittberner | aa2b87682f | ||
Jan Dittberner | f2db400ed8 | ||
Jan Dittberner | adae20cc7d | ||
Jan Dittberner | 26aae0173d | ||
Jan Dittberner | cbd8e37e8e | ||
Jan Dittberner | 5361f9e82e | ||
Jan Dittberner | e15c3a1fd9 | ||
Jan Dittberner | b4ba90a7c9 | ||
Jan Dittberner | b71fbf78ff | ||
Jan Dittberner | 821e84f608 | ||
Jan Dittberner | d5a275dbbe | ||
Jan Dittberner | 4eb3a1c3f3 | ||
Jan Dittberner | 8d14826169 | ||
Jan Dittberner | 88d8a29a14 | ||
Jan Dittberner | 20d5a86a71 | ||
Jan Dittberner | cbb695137c | ||
Jan Dittberner | f64a87714d | ||
Jan Dittberner | 62e1e8bad7 | ||
Jan Dittberner | dee8aa71a4 | ||
Jan Dittberner | 2b74fe99e0 | ||
Jan Dittberner | 2807ae5451 | ||
Jan Dittberner | 420d34dfea | ||
Jan Dittberner | dd866381be | ||
Jan Dittberner | 92beb28816 | ||
Jan Dittberner | 0db08db831 | ||
Jan Dittberner | 7dbb51da1a | ||
Jan Dittberner | 307ccf4307 | ||
Jan Dittberner | 4e144fb49d | ||
Jan Dittberner | 735a468806 |
17
.dockerignore
Normal file
17
.dockerignore
Normal file
|
@ -0,0 +1,17 @@
|
|||
**/*.pyc
|
||||
**/.*.swp
|
||||
**/.coverage
|
||||
**/__pycache__
|
||||
.dockerignore
|
||||
.env
|
||||
.envrc
|
||||
.git
|
||||
.gitignore
|
||||
.idea
|
||||
.vagrant
|
||||
Dockerfile
|
||||
Vagrantfile
|
||||
change-vmdebootstrap-default-dhcp.sh
|
||||
coverage-report
|
||||
docs
|
||||
salt
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -41,3 +41,6 @@ Desktop.ini
|
|||
.ropeproject
|
||||
_build/
|
||||
*.sqlite3
|
||||
.vagrant/
|
||||
.idea/
|
||||
.env
|
||||
|
|
64
Dockerfile
Normal file
64
Dockerfile
Normal file
|
@ -0,0 +1,64 @@
|
|||
ARG DEBIAN_RELEASE=buster
|
||||
FROM debian:$DEBIAN_RELEASE AS builder
|
||||
|
||||
ARG GVAAPP=gvafile
|
||||
ARG POETRY_VERSION=1.3.1
|
||||
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
curl \
|
||||
git \
|
||||
python3-dev \
|
||||
python3-setuptools \
|
||||
python3-virtualenv \
|
||||
python3-wheel
|
||||
|
||||
RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/root/.local POETRY_VERSION=$POETRY_VERSION python3 - \
|
||||
&& /root/.local/bin/poetry config virtualenvs.in-project true
|
||||
|
||||
WORKDIR /srv/$GVAAPP
|
||||
|
||||
COPY poetry.lock pyproject.toml /srv/$GVAAPP/
|
||||
|
||||
RUN /root/.local/bin/poetry install --only=main
|
||||
|
||||
FROM debian:$DEBIAN_RELEASE
|
||||
LABEL maintainer="Jan Dittberner <jan@dittberner.info>"
|
||||
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
dumb-init \
|
||||
gettext \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-wheel \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
||||
|
||||
ARG GVAAPP=gvafile
|
||||
ARG GVAGID=2000
|
||||
ARG GVAUID=2000
|
||||
|
||||
WORKDIR /srv/$GVAAPP
|
||||
|
||||
RUN addgroup --gid $GVAGID $GVAAPP ; \
|
||||
adduser --home /home/$GVAAPP --shell /bin/bash --uid $GVAUID --gid $GVAGID --disabled-password \
|
||||
--gecos "User for gnuviechadmin component $GVAAPP" $GVAAPP
|
||||
|
||||
COPY --chown=$GVAAPP:$GVAAPP --from=builder /srv/$GVAAPP/.venv /srv/$GVAAPP/.venv
|
||||
|
||||
VOLUME /srv/$GVAAPP/$GVAAPP
|
||||
|
||||
COPY ${GVAAPP}.sh entrypoint.sh /srv/
|
||||
|
||||
ENTRYPOINT ["dumb-init", "/srv/entrypoint.sh"]
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2014, 2015 Jan Dittberner
|
||||
Copyright (c) 2014-2020 Jan Dittberner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
@ -10,4 +10,4 @@ customer management at `Jan Dittberner IT-Consulting & -Solutions
|
|||
|
||||
Read the :doc:`Installation instructions <install>` to get started locally.
|
||||
|
||||
The project page for gvafile is at http://dev.gnuviech-server.de/gvafile.
|
||||
The project page for gvafile is at http://git.dittberner.info/gnuviech/gvafile.
|
||||
|
|
29
Vagrantfile
vendored
Normal file
29
Vagrantfile
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = "debian/buster64"
|
||||
|
||||
config.vm.hostname = "gvafile.local"
|
||||
config.vm.network "private_network", ip: "172.16.3.4"
|
||||
|
||||
config.vm.synced_folder "../gvasalt/states/", "/srv/salt/"
|
||||
config.vm.synced_folder "../gvasalt/pillar/", "/srv/pillar/"
|
||||
|
||||
config.vm.provider :libvirt do |libvirt|
|
||||
libvirt.memory = 1024
|
||||
end
|
||||
|
||||
config.vm.provision :shell, path: "change-vmdebootstrap-default-dhcp.sh"
|
||||
|
||||
config.vm.provision :salt do |salt|
|
||||
salt.bootstrap_options = "-x python3"
|
||||
salt.minion_id = "gvafile"
|
||||
salt.masterless = true
|
||||
salt.run_highstate = true
|
||||
salt.verbose = true
|
||||
salt.colorize = true
|
||||
salt.log_level = "warning"
|
||||
salt.grains_config = "salt/grains"
|
||||
end
|
||||
end
|
15
change-vmdebootstrap-default-dhcp.sh
Normal file
15
change-vmdebootstrap-default-dhcp.sh
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
debootstrap_network=/etc/systemd/network/99-dhcp.network
|
||||
|
||||
if grep -q '^Name=\\*' "${debootstrap_network}"; then
|
||||
primary_nic=$(ls -1 /sys/class/net | grep -v lo |sort | head -1)
|
||||
sed -i "s/^Name=e\\*/Name=${primary_nic}/" \
|
||||
"${debootstrap_network}"
|
||||
systemctl restart systemd-networkd.service
|
||||
echo "Changed systemd network configuration"
|
||||
else
|
||||
echo "Systemd network configuration has already been changed"
|
||||
fi
|
|
@ -1,6 +1,25 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
* :release:`0.7.0 <2023-05-07>`
|
||||
* :support:`-` switch from Pipenv to Poetry
|
||||
|
||||
* :release:`0.6.0 <2020-04-10>`
|
||||
* :support:`-` add Docker setup for lightweight local testing
|
||||
* :support:`-` update Vagrant setup to libvirt and Debian Buster
|
||||
* :support:`-` move fileservertasks to top level to keep the task names when
|
||||
using Python 3
|
||||
* :support:`2` use Pipenv for dependency management
|
||||
|
||||
* :release:`0.5.1 <2019-09-08>`
|
||||
* :bug:`-` change dependency URLs
|
||||
|
||||
* :release:`0.5.0 <2015-01-29>`
|
||||
* :feature:`-` add new task set_file_ssh_authorized_keys to add SSH keys for
|
||||
users
|
||||
* :support:`-` improved logging in fileservertasks.tasks, got rid of
|
||||
GVAFileException
|
||||
|
||||
* :release:`0.4.0 <2015-01-26>`
|
||||
* :feature:`-` implement new tasks create_file_website_hierarchy and
|
||||
delete_file_website_hierarchy
|
||||
|
|
|
@ -7,38 +7,26 @@ gvafile is implemented as a set of `Celery`_ tasks.
|
|||
.. _Celery: http://www.celeryproject.org/
|
||||
|
||||
|
||||
The project module :py:mod:`gvafile`
|
||||
====================================
|
||||
|
||||
.. automodule:: gvafile
|
||||
|
||||
|
||||
:py:mod:`celery <gvafile.celery>`
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: gvafile.celery
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`exceptions <gvafile.exceptions>`
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: gvafile.exceptions
|
||||
|
||||
|
||||
:py:mod:`settings <gvafile.settings>`
|
||||
-------------------------------------
|
||||
|
||||
.. automodule:: gvafile.settings
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`fileservertasks` app
|
||||
=============================
|
||||
:py:mod:`fileservertasks` module
|
||||
================================
|
||||
|
||||
.. automodule:: fileservertasks
|
||||
|
||||
|
||||
:py:mod:`celery <fileservertasks.celery>`
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: fileservertasks.celery
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`settings <fileservertasks.settings>`
|
||||
---------------------------------------------
|
||||
|
||||
.. automodule:: fileservertasks.settings
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`tasks <fileservertasks.tasks>`
|
||||
---------------------------------------
|
||||
|
||||
|
|
148
docs/conf.py
148
docs/conf.py
|
@ -18,164 +18,168 @@ import os
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath(os.path.join('..', 'gvafile')))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join("..", "gvafile")))
|
||||
|
||||
os.environ['GVAFILE_ALLOWED_HOSTS'] = 'localhost'
|
||||
os.environ['GVAFILE_SERVER_EMAIL'] = 'root@localhost'
|
||||
os.environ['GVAFILE_SFTP_DIRECTORY'] = '/home/www'
|
||||
os.environ['GVAFILE_MAIL_DIRECTORY'] = '/home/mail'
|
||||
os.environ["GVAFILE_BROKER_URL"] = "amqp://"
|
||||
os.environ["GVAFILE_ALLOWED_HOSTS"] = "localhost"
|
||||
os.environ["GVAFILE_MAIL_DIRECTORY"] = "/home/mail"
|
||||
os.environ["GVAFILE_RESULTS_REDIS_URL"] = "redis://"
|
||||
os.environ["GVAFILE_SERVER_EMAIL"] = "root@localhost"
|
||||
os.environ["GVAFILE_SFTP_AUTHKEYS_DIRECTORY"] = "/srv/sftp/authorized_keys"
|
||||
os.environ["GVAFILE_SFTP_DIRECTORY"] = "/home/www"
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['releases', 'sphinx.ext.autodoc', 'celery.contrib.sphinx']
|
||||
extensions = ["releases", "sphinx.ext.autodoc", "celery.contrib.sphinx"]
|
||||
|
||||
# configuration for releases extension
|
||||
releases_issue_uri = "https://git.dittberner.info/gnuviech/gvafile/issues/%s"
|
||||
releases_release_uri = "https://git.dittberner.info/gnuviech/gvafile/src/tag/%s"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
releases_issue_uri = 'https://dev.gnuviech-server.de/gvafile/ticket/%s'
|
||||
|
||||
releases_release_uri = 'https://dev.gnuviech-server.de/gvafile/milestone/%s'
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u'gvafile'
|
||||
copyright = u'2014, 2015 Jan Dittberner'
|
||||
project = u"gvafile"
|
||||
copyright = u"2014-2020, Jan Dittberner"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.4.0'
|
||||
from fileservertasks import __version__ as release
|
||||
|
||||
# The short X.Y version.
|
||||
version = ".".join(release.split(".")[:2])
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
# modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = "alabaster"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'gvafiledoc'
|
||||
htmlhelp_basename = "gvafiledoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
@ -183,10 +187,8 @@ htmlhelp_basename = 'gvafiledoc'
|
|||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
@ -194,42 +196,38 @@ latex_elements = {
|
|||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'gvafile.tex', u'gvafile Documentation',
|
||||
u'Jan Dittberner', 'manual'),
|
||||
("index", "gvafile.tex", u"gvafile Documentation", u"Jan Dittberner", "manual")
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'gvafile', u'gvafile Documentation',
|
||||
[u'Jan Dittberner'], 1)
|
||||
]
|
||||
man_pages = [("index", "gvafile", u"gvafile Documentation", [u"Jan Dittberner"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
@ -238,16 +236,22 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'gvafile', u'gvafile Documentation',
|
||||
u'Jan Dittberner', 'gvafile', 'GNUViech admin fileserver tools.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"gvafile",
|
||||
u"gvafile Documentation",
|
||||
u"Jan Dittberner",
|
||||
"gvafile",
|
||||
"GNUViech admin fileserver tools.",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
|
|
@ -7,4 +7,4 @@ of the following steps:
|
|||
* installation of native dependencies
|
||||
* setup of a virtualenv
|
||||
* installation of gvafile production dependencies inside the virtualenv
|
||||
* setup of celery worker under control of supervisord
|
||||
* setup of celery worker under control of systemd
|
||||
|
|
|
@ -7,77 +7,30 @@ Install
|
|||
Working Environment
|
||||
===================
|
||||
|
||||
You have several options in setting up your working environment. We recommend
|
||||
using virtualenv to separate the dependencies of your project from your
|
||||
system's python environment. If on Linux or Mac OS X, you can also use
|
||||
virtualenvwrapper to help manage multiple virtualenvs across different
|
||||
projects.
|
||||
To get a running work environment use `pipenv`_.
|
||||
|
||||
.. index:: virtualenv
|
||||
.. _pipenv: https://pipenv.kennethreitz.org/en/latest/
|
||||
|
||||
Virtualenv Only
|
||||
---------------
|
||||
|
||||
First, make sure you are using `virtualenv`_. Once that's installed, create
|
||||
your virtualenv:
|
||||
To get started install `pip` and `pipenv` and use `pipenv install --dev`:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ virtualenv --distribute gvafile
|
||||
|
||||
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
|
||||
|
||||
You will also need to ensure that the virtualenv has the project directory
|
||||
added to the path.
|
||||
|
||||
.. index:: virtualenvwrapper
|
||||
|
||||
Virtualenv with virtualenvwrapper
|
||||
------------------------------------
|
||||
|
||||
In Linux and Mac OSX, you can install `virtualenvwrapper
|
||||
<http://virtualenvwrapper.readthedocs.org/en/latest/>`_, which will take care
|
||||
of managing your virtual environments and adding the project path to the
|
||||
`site-directory` for you:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ mkdir gvafile
|
||||
$ mkvirtualenv -a gvafile gvafile-dev
|
||||
$ cd gvafile && add2virtualenv `pwd`
|
||||
|
||||
|
||||
.. index:: pip, requirements, dependencies
|
||||
|
||||
Installation of Dependencies
|
||||
=============================
|
||||
|
||||
Depending on where you are installing dependencies:
|
||||
|
||||
In development:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ pip install -r requirements/local.txt
|
||||
|
||||
For production:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ pip install -r requirements.txt
|
||||
$ apt install python3-pip
|
||||
$ python3 -m pip install --user -U pipenv
|
||||
$ pipenv install --dev
|
||||
|
||||
.. index:: celery, worker, file queue
|
||||
|
||||
Running the Celery worker
|
||||
=========================
|
||||
|
||||
gvafile uses the `Celery`_ distributed task queue system. The gvafile logix is
|
||||
gvafile uses the `Celery`_ distributed task queue system. The gvafile logic is
|
||||
executed by a celery worker. After all dependencies are installed you can go
|
||||
into the gvafile directory and run the celery worker with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ cd gvafile
|
||||
$ celery -A gvafile worker -Q file -l info
|
||||
$ pipenv run celery -A filerservertasks worker -Q web -l info
|
||||
|
||||
.. _Celery: http://www.celeryproject.org/
|
||||
|
|
5
entrypoint.sh
Executable file
5
entrypoint.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
su -c /srv/gvafile.sh gvafile
|
12
gvafile.sh
Executable file
12
gvafile.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
QUEUE="file"
|
||||
TASKS="fileservertasks"
|
||||
APP="gvafile"
|
||||
export TZ="Europe/Berlin"
|
||||
|
||||
. "/srv/${APP}/.venv/bin/activate"
|
||||
cd /srv/${APP}/${APP}
|
||||
celery -A "${TASKS}" worker -Q "${QUEUE}" -E -l info
|
|
@ -2,3 +2,8 @@
|
|||
This module contains :py:mod:`fileservertasks.tasks`.
|
||||
|
||||
"""
|
||||
__version__ = "0.7.0"
|
||||
|
||||
from fileservertasks.celery import app as celery_app
|
||||
|
||||
__all__ = ("celery_app",)
|
||||
|
|
|
@ -9,7 +9,7 @@ from __future__ import absolute_import
|
|||
from celery import Celery
|
||||
|
||||
#: The Celery application
|
||||
app = Celery('gvafile')
|
||||
app = Celery('fileservertasks')
|
||||
|
||||
app.config_from_object('gvafile.settings')
|
||||
app.autodiscover_tasks(['fileservertasks'], force=True)
|
||||
app.config_from_object('fileservertasks.settings', namespace="CELERY")
|
||||
app.autodiscover_tasks(['fileservertasks.tasks'], force=True)
|
|
@ -8,7 +8,7 @@ Common settings and globals.
|
|||
from os import environ
|
||||
|
||||
|
||||
def get_env_setting(setting):
|
||||
def get_env_variable(setting):
|
||||
"""
|
||||
Get the environment setting or return exception.
|
||||
|
||||
|
@ -25,21 +25,20 @@ def get_env_setting(setting):
|
|||
|
||||
|
||||
########## CELERY CONFIGURATION
|
||||
CELERY_TIMEZONE = 'Europe/Berlin'
|
||||
CELERY_ENABLE_UTC = True
|
||||
CELERY_RESULT_BACKEND = 'amqp'
|
||||
CELERY_RESULT_PERSISTENT = True
|
||||
CELERY_TASK_RESULT_EXPIRES = None
|
||||
CELERY_ROUTES = (
|
||||
'gvacommon.celeryrouters.GvaRouter',
|
||||
)
|
||||
CELERY_ACCEPT_CONTENT = ['json']
|
||||
CELERY_TASK_SERIALIZER = 'json'
|
||||
CELERY_RESULT_SERIALIZER = 'json'
|
||||
BROKER_URL = get_env_setting('GVAFILE_BROKER_URL')
|
||||
accept_content = ["json"]
|
||||
broker_url = get_env_variable("GVAFILE_BROKER_URL")
|
||||
enable_utc = True
|
||||
result_backend = get_env_variable("GVAFILE_RESULTS_REDIS_URL")
|
||||
result_expires = None
|
||||
result_persistent = True
|
||||
result_serializer = "json"
|
||||
task_routes = ("gvacommon.celeryrouters.GvaRouter",)
|
||||
task_serializer = "json"
|
||||
timezone = "Europe/Berlin"
|
||||
########## END CELERY CONFIGURATION
|
||||
|
||||
########## GVAFILE CONFIGURATION
|
||||
GVAFILE_SFTP_DIRECTORY = get_env_setting('GVAFILE_SFTP_DIRECTORY')
|
||||
GVAFILE_MAIL_DIRECTORY = get_env_setting('GVAFILE_MAIL_DIRECTORY')
|
||||
GVAFILE_SFTP_DIRECTORY = get_env_variable("GVAFILE_SFTP_DIRECTORY")
|
||||
GVAFILE_MAIL_DIRECTORY = get_env_variable("GVAFILE_MAIL_DIRECTORY")
|
||||
GVAFILE_SFTP_AUTHKEYS_DIRECTORY = get_env_variable("GVAFILE_SFTP_AUTHKEYS_DIRECTORY")
|
||||
########## END GVAFILE CONFIGURATION
|
|
@ -6,18 +6,17 @@ This module defines `Celery`_ tasks to manage file system entities.
|
|||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from copy import deepcopy
|
||||
import os
|
||||
import subprocess
|
||||
from tempfile import mkstemp
|
||||
|
||||
from gvafile import settings
|
||||
from fileservertasks import settings
|
||||
|
||||
from celery import shared_task
|
||||
from celery.utils.log import get_task_logger
|
||||
|
||||
from gvafile.exceptions import GVAFileException
|
||||
|
||||
|
||||
_logger = get_task_logger(__name__)
|
||||
_LOGGER = get_task_logger(__name__)
|
||||
|
||||
SUDO_CMD = '/usr/bin/sudo'
|
||||
INSTALL_CMD = '/usr/bin/install'
|
||||
|
@ -25,6 +24,34 @@ SETFACL_CMD = '/usr/bin/setfacl'
|
|||
RM_CMD = '/bin/rm'
|
||||
|
||||
|
||||
def log_and_raise(exception, message, *args):
|
||||
"""
|
||||
Log and raise a :py:class:`subprocess.CalledProcessError`.
|
||||
|
||||
:param exception: exception
|
||||
:param str message: log message
|
||||
:param args: arguments to fill placeholders in message
|
||||
:raises Exception: raises an exception with the formatted message
|
||||
|
||||
"""
|
||||
logargs = list(args) + [exception.returncode, exception.output]
|
||||
_LOGGER.error(message + "\nreturncode: %d\noutput:\n%s", *logargs)
|
||||
raise Exception(message % args)
|
||||
|
||||
|
||||
def _build_authorized_keys_path(username):
|
||||
"""
|
||||
Constructs the file path for the authorized_keys file for a given username.
|
||||
|
||||
:param str username: the user name
|
||||
:return: the file name
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
return os.path.join(
|
||||
settings.GVAFILE_SFTP_AUTHKEYS_DIRECTORY, username, 'keys')
|
||||
|
||||
|
||||
def _build_sftp_directory_name(username):
|
||||
"""
|
||||
Constructs the SFTP directory name for a given username.
|
||||
|
@ -42,15 +69,25 @@ def _build_mail_directory_name(username):
|
|||
|
||||
|
||||
@shared_task
|
||||
def setup_file_sftp_userdir(username):
|
||||
def setup_file_sftp_userdir(username, *args, **kwargs):
|
||||
"""
|
||||
This task creates the home directory for an SFTP user if it does not exist
|
||||
yet.
|
||||
|
||||
:param str username: the user name
|
||||
:param str username: the username
|
||||
:raises Exception: if the SFTP directory of the user cannot be created
|
||||
:return: the created directory name
|
||||
:rtype: str
|
||||
:return: a dictionary with the key :py:const:`username` set to the
|
||||
username value and a new key :py:const:`sftp_directory` set to the
|
||||
path of the created SFTP directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.setup_file_sftp_userdir_chained`
|
||||
at other positions in the task chain.
|
||||
|
||||
"""
|
||||
sftp_directory = _build_sftp_directory_name(username)
|
||||
|
@ -61,24 +98,57 @@ def setup_file_sftp_userdir(username):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, SETFACL_CMD, '-m', 'www-data:--x',
|
||||
sftp_directory], stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not create SFTP directory for user %s', username)
|
||||
raise GVAFileException(
|
||||
"could not create SFTP directory for user %s" % username)
|
||||
return sftp_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not create SFTP directory %s for user %s',
|
||||
sftp_directory, username)
|
||||
_LOGGER.info(
|
||||
'created sftp directory %s for user %s', sftp_directory, username)
|
||||
return {'username': username, 'sftp_directory': sftp_directory}
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_sftp_userdir(username):
|
||||
def setup_file_sftp_userdir_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task creates the home directory for an SFTP user if it does not exist
|
||||
yet.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` key
|
||||
:raises Exception: if the SFTP directory of the user cannot be created
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`sftp_directory` key set to the path of the created SFTP
|
||||
directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(setup_file_sftp_userdir(username))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_sftp_userdir(username, *args, **kwargs):
|
||||
"""
|
||||
This task recursively deletes the home directory of an SFTP user if it
|
||||
does not exist yet.
|
||||
exists.
|
||||
|
||||
:param str username: the user name
|
||||
:param str username: the username
|
||||
:raises Exception: if the SFTP directory of the user cannot be removed
|
||||
:return: the removed directory name
|
||||
:rtype: str
|
||||
:return: a dictionary with the key :py:const:`username` set to the username
|
||||
value and the new key :py:const:`sftp_directory` set to the path of the
|
||||
deleted SFTP directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.delete_file_sftp_userdir_chained`
|
||||
at other positions in the task chain.
|
||||
|
||||
"""
|
||||
sftp_directory = _build_sftp_directory_name(username)
|
||||
|
@ -86,25 +156,57 @@ def delete_file_sftp_userdir(username):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, '-r', '-f', sftp_directory],
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not remove SFTP directory for user %s', username)
|
||||
raise GVAFileException(
|
||||
"could not remove SFTP directory for user %s" % username)
|
||||
return sftp_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not remove SFTP directory for user %s', username)
|
||||
_LOGGER.info(
|
||||
"deleted sftp directory %s of user %s", sftp_directory, username)
|
||||
return {'username': username, 'sftp_directory': sftp_directory}
|
||||
|
||||
|
||||
@shared_task
|
||||
def setup_file_mail_userdir(username):
|
||||
def delete_file_sftp_userdir_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task recursively deletes the home directory of an SFTP user if it
|
||||
exists.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` key
|
||||
:raises Exception: if the SFTP directory of the user cannot be removed
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`sftp_directory` key set to the path of the removed SFTP
|
||||
directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(delete_file_sftp_userdir(username))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def setup_file_mail_userdir(username, *args, **kwargs):
|
||||
"""
|
||||
This task creates the mail base directory for a user if it does not exist
|
||||
yet.
|
||||
|
||||
:param str username: the user name
|
||||
:param str username: the username
|
||||
:raises Exception: if the mail base directory for the user cannot be
|
||||
created
|
||||
:return: the created directory name
|
||||
:rtype: str
|
||||
:return: a dictionary with the key :py:const:`username` set to the
|
||||
username value and a new key :py:const:`mail_directory` set to the path
|
||||
of the created mail directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.setup_file_mail_userdir_chained`
|
||||
at other positions in the task chain.
|
||||
|
||||
"""
|
||||
mail_directory = _build_mail_directory_name(username)
|
||||
|
@ -112,24 +214,57 @@ def setup_file_mail_userdir(username):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||
'-m', '0500', '-d', mail_directory], stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not create mail base directory for user %s', username)
|
||||
raise GVAFileException(
|
||||
"could not create mail base directory for user %s" % username)
|
||||
return mail_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not create mail base directory for user %s', username)
|
||||
_LOGGER.info(
|
||||
'created mail directory %s for user %s', mail_directory, username)
|
||||
return {'username': username, 'mail_directory': mail_directory}
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_mail_userdir(username):
|
||||
def setup_file_mail_userdir_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task creates the mail base directory for a user if it does not exist
|
||||
yet.
|
||||
|
||||
:param dict previous_result: a dictionary containing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` key
|
||||
:raises Exception: if the mail base directory for the user cannot be
|
||||
created
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`mail_directory` key set to the path of the created mail
|
||||
directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(setup_file_mail_userdir(username))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_mail_userdir(username, *args, **kwargs):
|
||||
"""
|
||||
This task recursively deletes the mail base directory for a user if it
|
||||
does not exist yet.
|
||||
|
||||
:param str username: the user name
|
||||
:raises Exception: if the mail base directory of the user cannot be removed
|
||||
:return: the removed directory name
|
||||
:rtype: str
|
||||
:param str username: the username
|
||||
:raises Exception: if the mail base directory of the user cannot be deleted
|
||||
:return: a dictionary with the key :py:const:`username` set to the
|
||||
username value and a new key :py:const:`mail_directory` set to the path
|
||||
of the deleted mail directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.delete_file_mail_userdir_chained`
|
||||
at other positions in the task chain.
|
||||
|
||||
"""
|
||||
mail_directory = _build_mail_directory_name(username)
|
||||
|
@ -137,25 +272,57 @@ def delete_file_mail_userdir(username):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, '-r', '-f', mail_directory],
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not remove mail base directory of user %s', username)
|
||||
raise GVAFileException(
|
||||
"could not remove mail base directory of user %s" % username)
|
||||
return mail_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not remove mail base directory of user %s', username)
|
||||
_LOGGER.info(
|
||||
'deleted mail directory %s of user %s', mail_directory, username)
|
||||
return {'username': username, 'mail_directory': mail_directory}
|
||||
|
||||
@shared_task
|
||||
def delete_file_mail_userdir_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task recursively deletes the mail base directory for a user if it
|
||||
does not exist yet.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` key
|
||||
:raises Exception: if the mail base directory of the user cannot be deleted
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`mail_directory` key set to the path of the deleted mail
|
||||
directory
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(delete_file_mail_userdir(username))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def create_file_mailbox(username, mailboxname):
|
||||
def create_file_mailbox(username, mailboxname, *args, **kwargs):
|
||||
"""
|
||||
This task creates a new mailbox directory for the given user and mailbox
|
||||
name.
|
||||
|
||||
:param str username: the user name
|
||||
:param str username: the username
|
||||
:param str mailboxname: the mailbox name
|
||||
:raises GVAFileException: if the mailbox directory cannot be created
|
||||
:return: the created mailbox directory name
|
||||
:rtype: str
|
||||
:raises Exception: if the mailbox directory cannot be created
|
||||
:return: a dictionary with the keys :py:const:`username` and
|
||||
:py:const:`mailboxname` set to the values of username and mailboxname
|
||||
and a new key :py:const:`mailbox_directory` set to the path of the
|
||||
created mailbox directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.create_file_mailbox_chained` at
|
||||
other positions in the task chain.
|
||||
|
||||
"""
|
||||
mailbox_directory = os.path.join(
|
||||
|
@ -164,25 +331,63 @@ def create_file_mailbox(username, mailboxname):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||
'-m', '0700', '-d', mailbox_directory], stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not create mailbox %s for user %s', mailboxname, username)
|
||||
raise GVAFileException(
|
||||
"could not create mailbox %s for user %s" % (mailboxname, username)
|
||||
)
|
||||
return mailbox_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not create mailbox %s for user %s', mailboxname,
|
||||
username)
|
||||
_LOGGER.info(
|
||||
'created mailbox directory %s for user %s', mailbox_directory,
|
||||
username)
|
||||
return {
|
||||
'username': username, 'mailboxname': mailboxname,
|
||||
'mailbox_directory': mailbox_directory
|
||||
}
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_mailbox(username, mailboxname):
|
||||
def create_file_mailbox_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task creates a new mailbox directory for the given user and mailbox
|
||||
name.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` and a :py:const:`mailboxname` key
|
||||
:raises Exception: if the mailbox directory cannot be created
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`mailbox_directory` key set to the path of the created
|
||||
mailbox directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
mailboxname = previous_result['mailboxname']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(create_file_mailbox(username, mailboxname))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_mailbox(username, mailboxname, *args, **kwargs):
|
||||
"""
|
||||
This task deletes the given mailbox of the given user.
|
||||
|
||||
:param str username: the user name
|
||||
:param str username: the username
|
||||
:param str mailboxname: the mailbox name
|
||||
:raises GVAFileException: if the mailbox directory cannot be deleted
|
||||
:return: the deleted mailbox directory name
|
||||
:rtype: str
|
||||
:raises Exception: if the mailbox directory cannot be deleted
|
||||
:return: a dictionary with the keys :py:const:`username` and
|
||||
:py:const:`mailboxname` set to the values of username and mailboxname
|
||||
and a new key :py:const:`mailbox_directory` set to the path of the
|
||||
deleted mailbox directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use :py:func:`fileservertasks.tasks.delete_file_mailbox_chained` for
|
||||
other positions in the task chain.
|
||||
|
||||
"""
|
||||
mailbox_directory = os.path.join(
|
||||
|
@ -191,23 +396,62 @@ def delete_file_mailbox(username, mailboxname):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, '-r', '-f', mailbox_directory],
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
'could not remove mailbox %s of user %s', mailboxname, username)
|
||||
raise GVAFileException(
|
||||
"could not remove mailbox %s of user %s" % (mailboxname, username))
|
||||
return mailbox_directory
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not remove mailbox %s of user %s', mailboxname,
|
||||
username)
|
||||
_LOGGER.info(
|
||||
'deleted mailbox directory %s of user %s', mailbox_directory, username)
|
||||
return {
|
||||
'username': username, 'mailboxname': mailboxname,
|
||||
'mailbox_directory': mailbox_directory
|
||||
}
|
||||
|
||||
@shared_task
|
||||
def delete_file_mailbox_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task deletes the given mailbox of the given user.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` and a :py:const:`mailboxname` key
|
||||
:raises Exception: if the mailbox directory cannot be deleted
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`mailbox_directory` key set to the path of the deleted
|
||||
mailbox directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
mailboxname = previous_result['mailboxname']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(delete_file_mailbox(username, mailboxname))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def create_file_website_hierarchy(username, sitename):
|
||||
def create_file_website_hierarchy(username, sitename, *args, **kwargs):
|
||||
"""
|
||||
This task creates the directory hierarchy for a website.
|
||||
|
||||
:param str username: the user name
|
||||
:param str sitename: name of the website
|
||||
:return: the directory name
|
||||
:rtype: str
|
||||
:param str username: the username
|
||||
:param str sitename: the sitename
|
||||
:raises Exception: if the website directory hierarchy directory cannot be
|
||||
created
|
||||
:return: a dictionary with the keys :py:const:`username` and
|
||||
:py:const:`sitename` set to the values of username and sitename and a
|
||||
new key :py:const:`website_directory` set to the path of the created
|
||||
website directory
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use
|
||||
:py:func:`fileservertasks.tasks.create_file_website_hierarchy_chained`
|
||||
at other positions in the task chain
|
||||
|
||||
"""
|
||||
website_directory = os.path.join(
|
||||
|
@ -233,25 +477,63 @@ def create_file_website_hierarchy(username, sitename):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||
'-m', '0750', '-d', tmpdir], stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe,
|
||||
("could not setup website file hierarchy for user %s's "
|
||||
"website %s"), username, sitename)
|
||||
raise GVAFileException(
|
||||
("could not setup website file hierarchy for user %s's "
|
||||
"website %s") % (username, sitename))
|
||||
return website_directory
|
||||
_LOGGER.info(
|
||||
'created website directory %s for user %s', website_directory,
|
||||
username)
|
||||
return {
|
||||
'username': username, 'sitename': sitename,
|
||||
'website_directory': website_directory,
|
||||
}
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_website_hierarchy(username, sitename):
|
||||
def create_file_website_hierarchy_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task deletes the website hierarchy recursively.
|
||||
This task creates the directory hierarchy for a website.
|
||||
|
||||
:param str username: the user name
|
||||
:param str sitename: name of the website
|
||||
:return: the directory name
|
||||
:rtype: str
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` and a :py:const:`sitename` key
|
||||
:raises Exception: if the website directory hierarchy directory cannot be
|
||||
created
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`website_directory` key set to the path of the created
|
||||
website directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
sitename = previous_result['sitename']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(create_file_website_hierarchy(username, sitename))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_website_hierarchy(username, sitename, *args, **kwargs):
|
||||
"""
|
||||
This task deletes a website hierarchy recursively.
|
||||
|
||||
:param str username: a username
|
||||
:param str sitename: a site name
|
||||
:return: a dictionary with the keys :py:const:`username` and
|
||||
:py:const:`sitename` set to their original values and a new key
|
||||
:py:const:`website_directory` set to the path of the deleted website
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use
|
||||
:py:func:`fileservertasks.tasks.delete_file_website_hierarchy_chained`
|
||||
at other positions in the task chain
|
||||
|
||||
"""
|
||||
website_directory = os.path.join(
|
||||
|
@ -260,11 +542,129 @@ def delete_file_website_hierarchy(username, sitename):
|
|||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, '-r', '-f', website_directory],
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
_logger.exception(
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe,
|
||||
("could not delete the website file hierarchy of user %s's "
|
||||
"website %s"), username, sitename)
|
||||
raise GVAFileException(
|
||||
("could not delete the website file hierarchy of user %s's "
|
||||
"website %s") % (username, sitename))
|
||||
return website_directory
|
||||
_LOGGER.info(
|
||||
'deleted website directory %s of user %s', website_directory, username)
|
||||
return {
|
||||
'username': username, 'sitename': sitename,
|
||||
'website_directory': website_directory,
|
||||
}
|
||||
|
||||
|
||||
@shared_task
|
||||
def delete_file_website_hierarchy_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task deletes the website hierarchy recursively.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` and a :py:const:`sitename` key
|
||||
:raises Exception: if the website directory hierarchy directory cannot be
|
||||
deleted
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`website_directory` set to the path of the deleted website
|
||||
directory
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
sitename = previous_result['sitename']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(delete_file_website_hierarchy(username, sitename))
|
||||
return retval
|
||||
|
||||
|
||||
@shared_task
|
||||
def set_file_ssh_authorized_keys(username, ssh_keys, *args, **kwargs):
|
||||
"""
|
||||
This task set the authorized keys for ssh logins.
|
||||
|
||||
:param str username: a username
|
||||
:param list ssh_keys: a list of ssh keys
|
||||
:raises Exception: if the update of the creation or update of ssh
|
||||
authorized_keys failed
|
||||
:return: a dictionary with the keys :py:const:`username` and
|
||||
:py:const:`ssh_keys` set to their original values and a new key
|
||||
:py:const:`ssh_authorized_keys` set to the path of the SSH
|
||||
authorized_keys file
|
||||
:rtype: dict
|
||||
|
||||
.. note::
|
||||
|
||||
This variant can only be used at the beginning of a Celery task chain
|
||||
or as a standalone task.
|
||||
|
||||
Use
|
||||
:py:func:`fileservertasks.tasks.set_file_ssh_authorized_keys_chained`
|
||||
at other positions in the task chain
|
||||
|
||||
"""
|
||||
ssh_authorized_keys_file = _build_authorized_keys_path(username)
|
||||
if ssh_keys:
|
||||
try:
|
||||
authkeystemp, filename = mkstemp()
|
||||
conffile = os.fdopen(authkeystemp, 'w')
|
||||
conffile.write("\n".join(ssh_keys))
|
||||
finally:
|
||||
if conffile:
|
||||
conffile.close()
|
||||
try:
|
||||
subprocess.check_output([
|
||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||
'-m', '0500', '-d', os.path.dirname(ssh_authorized_keys_file)],
|
||||
stderr=subprocess.STDOUT)
|
||||
subprocess.check_output([
|
||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||
'-m', '0400', filename, ssh_authorized_keys_file],
|
||||
stderr=subprocess.STDOUT)
|
||||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, filename], stderr=subprocess.STDOUT)
|
||||
_LOGGER.info(
|
||||
'set %d authorized_keys for user %s', len(ssh_keys), username)
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not write authorized_keys file for user %s',
|
||||
username)
|
||||
else:
|
||||
try:
|
||||
subprocess.check_output([
|
||||
SUDO_CMD, RM_CMD, '-rf',
|
||||
os.path.dirname(ssh_authorized_keys_file)],
|
||||
stderr=subprocess.STDOUT)
|
||||
_LOGGER.info(
|
||||
'deleted authorized_keys of user %s', username)
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
log_and_raise(
|
||||
cpe, 'could not remove the authorized_keys file of user %s',
|
||||
username)
|
||||
return {
|
||||
'username': username, 'ssh_keys': ssh_keys,
|
||||
'ssh_authorized_keys': ssh_authorized_keys_file,
|
||||
}
|
||||
|
||||
|
||||
@shared_task
|
||||
def set_file_ssh_authorized_keys_chained(previous_result, *args, **kwargs):
|
||||
"""
|
||||
This task sets the authorized keys for ssh logins.
|
||||
|
||||
:param dict previous_result: a dictionary describing the result of the
|
||||
previous step in the Celery task chain. This dictionary must contain a
|
||||
:py:const:`username` and a :py:const:`ssh_keys` key
|
||||
:raises Exception: if the update of the creation or update of ssh
|
||||
authorized_keys failed
|
||||
:return: a copy of the :py:obj:`previous_result` dictionary with a new
|
||||
:py:const:`ssh_authorized_keys` set to the path of the SSH
|
||||
authorized_keys file
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
username = previous_result['username']
|
||||
ssh_keys = previous_result['ssh_keys']
|
||||
retval = deepcopy(previous_result)
|
||||
retval.update(set_file_ssh_authorized_keys(username, ssh_keys))
|
||||
return retval
|
||||
|
|
3
gvafile/gvacommon/.gitignore
vendored
3
gvafile/gvacommon/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
.*.swp
|
||||
*.pyc
|
||||
.ropeproject/
|
|
@ -1,15 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class GvaRouter(object):
|
||||
|
||||
def route_for_task(self, task, args=None, kwargs=None):
|
||||
for route in ['ldap', 'file', 'mysql', 'pgsql', 'web']:
|
||||
for route in ["ldap", "file", "mysql", "pgsql", "web"]:
|
||||
if route in task:
|
||||
return {
|
||||
'exchange': route,
|
||||
'exchange_type': 'direct',
|
||||
'queue': route,
|
||||
}
|
||||
return {"exchange": route, "exchange_type": "direct", "queue": route}
|
||||
return None
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
"""
|
||||
This module defines mixins for gnuviechadmin views.
|
||||
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponseForbidden
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from braces.views import LoginRequiredMixin
|
||||
|
||||
|
||||
class StaffOrSelfLoginRequiredMixin(LoginRequiredMixin):
|
||||
"""
|
||||
Mixin that makes sure that a user is logged in and matches the current
|
||||
customer or is a staff user.
|
||||
|
||||
"""
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if (
|
||||
request.user.is_staff or
|
||||
request.user == self.get_customer_object()
|
||||
):
|
||||
return super(StaffOrSelfLoginRequiredMixin, self).dispatch(
|
||||
request, *args, **kwargs
|
||||
)
|
||||
return HttpResponseForbidden(
|
||||
_('You are not allowed to view this page.')
|
||||
)
|
||||
|
||||
def get_customer_object(self):
|
||||
"""
|
||||
Views based on this mixin have to implement this method to return
|
||||
the customer that must be an object of the same class as the
|
||||
django.contrib.auth user type.
|
||||
|
||||
:return: customer
|
||||
:rtype: settings.AUTH_USER_MODEL
|
||||
|
||||
"""
|
||||
raise NotImplemented("subclass has to implement get_customer_object")
|
|
@ -1,12 +0,0 @@
|
|||
"""
|
||||
This module defines exceptions for gvafile.
|
||||
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class GVAFileException(Exception):
|
||||
"""
|
||||
Generic Exception class for gvafile.
|
||||
|
||||
"""
|
975
poetry.lock
generated
Normal file
975
poetry.lock
generated
Normal file
|
@ -0,0 +1,975 @@
|
|||
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "alabaster"
|
||||
version = "0.7.13"
|
||||
description = "A configurable sidebar-enabled Sphinx theme"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
|
||||
{file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "amqp"
|
||||
version = "5.1.1"
|
||||
description = "Low-level AMQP client for Python (fork of amqplib)."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "amqp-5.1.1-py3-none-any.whl", hash = "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359"},
|
||||
{file = "amqp-5.1.1.tar.gz", hash = "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
vine = ">=5.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.6.0"
|
||||
description = "ASGI specs, helper code, and adapters"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "asgiref-3.6.0-py3-none-any.whl", hash = "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac"},
|
||||
{file = "asgiref-3.6.0.tar.gz", hash = "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
||||
|
||||
[[package]]
|
||||
name = "async-timeout"
|
||||
version = "4.0.2"
|
||||
description = "Timeout context manager for asyncio programs"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
|
||||
{file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""}
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.12.1"
|
||||
description = "Internationalization utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
|
||||
{file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
|
||||
|
||||
[[package]]
|
||||
name = "billiard"
|
||||
version = "3.6.4.0"
|
||||
description = "Python multiprocessing fork with improvements and bugfixes"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"},
|
||||
{file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cached-property"
|
||||
version = "1.5.2"
|
||||
description = "A decorator for caching properties in classes."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"},
|
||||
{file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "celery"
|
||||
version = "5.2.7"
|
||||
description = "Distributed Task Queue."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "celery-5.2.7-py3-none-any.whl", hash = "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14"},
|
||||
{file = "celery-5.2.7.tar.gz", hash = "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
billiard = ">=3.6.4.0,<4.0"
|
||||
click = ">=8.0.3,<9.0"
|
||||
click-didyoumean = ">=0.0.3"
|
||||
click-plugins = ">=1.1.1"
|
||||
click-repl = ">=0.2.0"
|
||||
importlib-metadata = {version = ">=1.4.0", markers = "python_version < \"3.8\""}
|
||||
kombu = ">=5.2.3,<6.0"
|
||||
pytz = ">=2021.3"
|
||||
vine = ">=5.0.0,<6.0"
|
||||
|
||||
[package.extras]
|
||||
arangodb = ["pyArango (>=1.3.2)"]
|
||||
auth = ["cryptography"]
|
||||
azureblockblob = ["azure-storage-blob (==12.9.0)"]
|
||||
brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"]
|
||||
cassandra = ["cassandra-driver (<3.21.0)"]
|
||||
consul = ["python-consul2"]
|
||||
cosmosdbsql = ["pydocumentdb (==2.3.2)"]
|
||||
couchbase = ["couchbase (>=3.0.0)"]
|
||||
couchdb = ["pycouchdb"]
|
||||
django = ["Django (>=1.11)"]
|
||||
dynamodb = ["boto3 (>=1.9.178)"]
|
||||
elasticsearch = ["elasticsearch"]
|
||||
eventlet = ["eventlet (>=0.32.0)"]
|
||||
gevent = ["gevent (>=1.5.0)"]
|
||||
librabbitmq = ["librabbitmq (>=1.5.0)"]
|
||||
memcache = ["pylibmc"]
|
||||
mongodb = ["pymongo[srv] (>=3.11.1)"]
|
||||
msgpack = ["msgpack"]
|
||||
pymemcache = ["python-memcached"]
|
||||
pyro = ["pyro4"]
|
||||
pytest = ["pytest-celery"]
|
||||
redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"]
|
||||
s3 = ["boto3 (>=1.9.125)"]
|
||||
slmq = ["softlayer-messaging (>=1.0.3)"]
|
||||
solar = ["ephem"]
|
||||
sqlalchemy = ["sqlalchemy"]
|
||||
sqs = ["kombu[sqs]"]
|
||||
tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"]
|
||||
yaml = ["PyYAML (>=3.10)"]
|
||||
zookeeper = ["kazoo (>=1.3.1)"]
|
||||
zstd = ["zstandard"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2022.12.7"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
|
||||
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.1.0"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
|
||||
{file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.3"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
||||
|
||||
[[package]]
|
||||
name = "click-didyoumean"
|
||||
version = "0.3.0"
|
||||
description = "Enables git-like *did-you-mean* feature in click"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2,<4.0.0"
|
||||
files = [
|
||||
{file = "click-didyoumean-0.3.0.tar.gz", hash = "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"},
|
||||
{file = "click_didyoumean-0.3.0-py3-none-any.whl", hash = "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=7"
|
||||
|
||||
[[package]]
|
||||
name = "click-plugins"
|
||||
version = "1.1.1"
|
||||
description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"},
|
||||
{file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=4.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "click-repl"
|
||||
version = "0.2.0"
|
||||
description = "REPL plugin for Click"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"},
|
||||
{file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = "*"
|
||||
prompt-toolkit = "*"
|
||||
six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.2.5"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "coverage-7.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:883123d0bbe1c136f76b56276074b0c79b5817dd4238097ffa64ac67257f4b6c"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d2fbc2a127e857d2f8898aaabcc34c37771bf78a4d5e17d3e1f5c30cd0cbc62a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f3671662dc4b422b15776cdca89c041a6349b4864a43aa2350b6b0b03bbcc7f"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780551e47d62095e088f251f5db428473c26db7829884323e56d9c0c3118791a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:066b44897c493e0dcbc9e6a6d9f8bbb6607ef82367cf6810d387c09f0cd4fe9a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9a4ee55174b04f6af539218f9f8083140f61a46eabcaa4234f3c2a452c4ed11"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:706ec567267c96717ab9363904d846ec009a48d5f832140b6ad08aad3791b1f5"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ae453f655640157d76209f42c62c64c4d4f2c7f97256d3567e3b439bd5c9b06c"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-win32.whl", hash = "sha256:f81c9b4bd8aa747d417407a7f6f0b1469a43b36a85748145e144ac4e8d303cb5"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:dc945064a8783b86fcce9a0a705abd7db2117d95e340df8a4333f00be5efb64c"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:40cc0f91c6cde033da493227797be2826cbf8f388eaa36a0271a97a332bfd7ce"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a66e055254a26c82aead7ff420d9fa8dc2da10c82679ea850d8feebf11074d88"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c10fbc8a64aa0f3ed136b0b086b6b577bc64d67d5581acd7cc129af52654384e"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a22cbb5ede6fade0482111fa7f01115ff04039795d7092ed0db43522431b4f2"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292300f76440651529b8ceec283a9370532f4ecba9ad67d120617021bb5ef139"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7ff8f3fb38233035028dbc93715551d81eadc110199e14bbbfa01c5c4a43f8d8"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a08c7401d0b24e8c2982f4e307124b671c6736d40d1c39e09d7a8687bddf83ed"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef9659d1cda9ce9ac9585c045aaa1e59223b143f2407db0eaee0b61a4f266fb6"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-win32.whl", hash = "sha256:30dcaf05adfa69c2a7b9f7dfd9f60bc8e36b282d7ed25c308ef9e114de7fc23b"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:97072cc90f1009386c8a5b7de9d4fc1a9f91ba5ef2146c55c1f005e7b5c5e068"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bebea5f5ed41f618797ce3ffb4606c64a5de92e9c3f26d26c2e0aae292f015c1"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828189fcdda99aae0d6bf718ea766b2e715eabc1868670a0a07bf8404bf58c33"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e8a95f243d01ba572341c52f89f3acb98a3b6d1d5d830efba86033dd3687ade"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8834e5f17d89e05697c3c043d3e58a8b19682bf365048837383abfe39adaed5"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1f25ee9de21a39b3a8516f2c5feb8de248f17da7eead089c2e04aa097936b47"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1637253b11a18f453e34013c665d8bf15904c9e3c44fbda34c643fbdc9d452cd"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8e575a59315a91ccd00c7757127f6b2488c2f914096077c745c2f1ba5b8c0969"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-win32.whl", hash = "sha256:509ecd8334c380000d259dc66feb191dd0a93b21f2453faa75f7f9cdcefc0718"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-win_amd64.whl", hash = "sha256:12580845917b1e59f8a1c2ffa6af6d0908cb39220f3019e36c110c943dc875b0"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b5016e331b75310610c2cf955d9f58a9749943ed5f7b8cfc0bb89c6134ab0a84"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:373ea34dca98f2fdb3e5cb33d83b6d801007a8074f992b80311fc589d3e6b790"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a063aad9f7b4c9f9da7b2550eae0a582ffc7623dca1c925e50c3fbde7a579771"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38c0a497a000d50491055805313ed83ddba069353d102ece8aef5d11b5faf045"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b3b05e22a77bb0ae1a3125126a4e08535961c946b62f30985535ed40e26614"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0342a28617e63ad15d96dca0f7ae9479a37b7d8a295f749c14f3436ea59fdcb3"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf97ed82ca986e5c637ea286ba2793c85325b30f869bf64d3009ccc1a31ae3fd"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c2c41c1b1866b670573657d584de413df701f482574bad7e28214a2362cb1fd1"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-win32.whl", hash = "sha256:10b15394c13544fce02382360cab54e51a9e0fd1bd61ae9ce012c0d1e103c813"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-win_amd64.whl", hash = "sha256:a0b273fe6dc655b110e8dc89b8ec7f1a778d78c9fd9b4bda7c384c8906072212"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c587f52c81211d4530fa6857884d37f514bcf9453bdeee0ff93eaaf906a5c1b"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4436cc9ba5414c2c998eaedee5343f49c02ca93b21769c5fdfa4f9d799e84200"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6599bf92f33ab041e36e06d25890afbdf12078aacfe1f1d08c713906e49a3fe5"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:857abe2fa6a4973f8663e039ead8d22215d31db613ace76e4a98f52ec919068e"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f5cab2d7f0c12f8187a376cc6582c477d2df91d63f75341307fcdcb5d60303"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa387bd7489f3e1787ff82068b295bcaafbf6f79c3dad3cbc82ef88ce3f48ad3"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:156192e5fd3dbbcb11cd777cc469cf010a294f4c736a2b2c891c77618cb1379a"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd3b4b8175c1db502adf209d06136c000df4d245105c8839e9d0be71c94aefe1"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-win32.whl", hash = "sha256:ddc5a54edb653e9e215f75de377354e2455376f416c4378e1d43b08ec50acc31"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:338aa9d9883aaaad53695cb14ccdeb36d4060485bb9388446330bef9c361c252"},
|
||||
{file = "coverage-7.2.5-pp37.pp38.pp39-none-any.whl", hash = "sha256:8877d9b437b35a85c18e3c6499b23674684bf690f5d96c1006a1ef61f9fdf0f3"},
|
||||
{file = "coverage-7.2.5.tar.gz", hash = "sha256:f99ef080288f09ffc687423b8d60978cf3a465d3f404a18d1a05474bd8575a47"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "3.2.19"
|
||||
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "Django-3.2.19-py3-none-any.whl", hash = "sha256:21cc991466245d659ab79cb01204f9515690f8dae00e5eabde307f14d24d4d7d"},
|
||||
{file = "Django-3.2.19.tar.gz", hash = "sha256:031365bae96814da19c10706218c44dff3b654cc4de20a98bd2d29b9bde469f0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
asgiref = ">=3.3.2,<4"
|
||||
pytz = "*"
|
||||
sqlparse = ">=0.2.2"
|
||||
|
||||
[package.extras]
|
||||
argon2 = ["argon2-cffi (>=19.1.0)"]
|
||||
bcrypt = ["bcrypt"]
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
version = "0.19"
|
||||
description = "Docutils -- Python Documentation Utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"},
|
||||
{file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gvacommon"
|
||||
version = "0.6.0"
|
||||
description = ""
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
files = [
|
||||
{file = "gvacommon-0.6.0-py3-none-any.whl", hash = "sha256:89977984ae8fd76860c326b0221a3327c48b7f3349ef058541770f0d1a3a55d8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
django = "<4"
|
||||
|
||||
[package.source]
|
||||
type = "legacy"
|
||||
url = "https://pypi.gnuviech-server.de/simple"
|
||||
reference = "gnuviech"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.4"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
||||
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imagesize"
|
||||
version = "1.4.1"
|
||||
description = "Getting image size from png/jpeg/jpeg2000/gif file"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
files = [
|
||||
{file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
|
||||
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "4.13.0"
|
||||
description = "Read metadata from Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"},
|
||||
{file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
|
||||
zipp = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
|
||||
perf = ["ipython"]
|
||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.2"
|
||||
description = "A very fast and expressive template engine."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
|
||||
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
MarkupSafe = ">=2.0"
|
||||
|
||||
[package.extras]
|
||||
i18n = ["Babel (>=2.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "kombu"
|
||||
version = "5.2.4"
|
||||
description = "Messaging library for Python."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "kombu-5.2.4-py3-none-any.whl", hash = "sha256:8b213b24293d3417bcf0d2f5537b7f756079e3ea232a8386dcc89a59fd2361a4"},
|
||||
{file = "kombu-5.2.4.tar.gz", hash = "sha256:37cee3ee725f94ea8bb173eaab7c1760203ea53bbebae226328600f9d2799610"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
amqp = ">=5.0.9,<6.0.0"
|
||||
cached-property = {version = "*", markers = "python_version < \"3.8\""}
|
||||
importlib-metadata = {version = ">=0.18", markers = "python_version < \"3.8\""}
|
||||
vine = "*"
|
||||
|
||||
[package.extras]
|
||||
azureservicebus = ["azure-servicebus (>=7.0.0)"]
|
||||
azurestoragequeues = ["azure-storage-queue"]
|
||||
consul = ["python-consul (>=0.6.0)"]
|
||||
librabbitmq = ["librabbitmq (>=2.0.0)"]
|
||||
mongodb = ["pymongo (>=3.3.0,<3.12.1)"]
|
||||
msgpack = ["msgpack"]
|
||||
pyro = ["pyro4"]
|
||||
qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"]
|
||||
redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"]
|
||||
slmq = ["softlayer-messaging (>=1.0.3)"]
|
||||
sqlalchemy = ["sqlalchemy"]
|
||||
sqs = ["boto3 (>=1.9.12)", "pycurl (>=7.44.1,<7.45.0)", "urllib3 (>=1.26.7)"]
|
||||
yaml = ["PyYAML (>=3.10)"]
|
||||
zookeeper = ["kazoo (>=1.3.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "2.1.2"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
|
||||
{file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
|
||||
{file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
|
||||
{file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
|
||||
{file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
|
||||
{file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
|
||||
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "23.1"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
|
||||
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.38"
|
||||
description = "Library for building powerful interactive command lines in Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
|
||||
{file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
wcwidth = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.15.1"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
|
||||
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
plugins = ["importlib-metadata"]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2023.3"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
|
||||
{file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "4.5.4"
|
||||
description = "Python client for Redis database and key-value store"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "redis-4.5.4-py3-none-any.whl", hash = "sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2"},
|
||||
{file = "redis-4.5.4.tar.gz", hash = "sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""}
|
||||
importlib-metadata = {version = ">=1.0", markers = "python_version < \"3.8\""}
|
||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
hiredis = ["hiredis (>=1.0.0)"]
|
||||
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "releases"
|
||||
version = "2.1.1"
|
||||
description = "A Sphinx extension for changelog manipulation"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "releases-2.1.1-py3-none-any.whl", hash = "sha256:cd06449c915ce9729aaebe19a836744998f83f9ebb0cf92e54949c88ab3402f1"},
|
||||
{file = "releases-2.1.1.tar.gz", hash = "sha256:ae0683c3f309931a3717c6976e0f079929d05d34214b432a95764e61367f58d1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
semantic-version = "<2.7"
|
||||
sphinx = ">=4"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.29.0"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "requests-2.29.0-py3-none-any.whl", hash = "sha256:e8f3c9be120d3333921d213eef078af392fba3933ab7ed2d1cba3b56f2568c3b"},
|
||||
{file = "requests-2.29.0.tar.gz", hash = "sha256:f2e34a75f4749019bb0e3effb66683630e4ffeaf75819fb51bebef1bf5aef059"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "semantic-version"
|
||||
version = "2.6.0"
|
||||
description = "A library implementing the 'SemVer' scheme."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "semantic_version-2.6.0-py3-none-any.whl", hash = "sha256:2d06ab7372034bcb8b54f2205370f4aa0643c133b7e6dbd129c5200b83ab394b"},
|
||||
{file = "semantic_version-2.6.0.tar.gz", hash = "sha256:2a4328680073e9b243667b201119772aefc5fc63ae32398d6afafff07c4f54c0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
files = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snowballstemmer"
|
||||
version = "2.2.0"
|
||||
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
|
||||
{file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sphinx"
|
||||
version = "5.3.0"
|
||||
description = "Python documentation generator"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
|
||||
{file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
alabaster = ">=0.7,<0.8"
|
||||
babel = ">=2.9"
|
||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||
docutils = ">=0.14,<0.20"
|
||||
imagesize = ">=1.3"
|
||||
importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
|
||||
Jinja2 = ">=3.0"
|
||||
packaging = ">=21.0"
|
||||
Pygments = ">=2.12"
|
||||
requests = ">=2.5.0"
|
||||
snowballstemmer = ">=2.0"
|
||||
sphinxcontrib-applehelp = "*"
|
||||
sphinxcontrib-devhelp = "*"
|
||||
sphinxcontrib-htmlhelp = ">=2.0.0"
|
||||
sphinxcontrib-jsmath = "*"
|
||||
sphinxcontrib-qthelp = "*"
|
||||
sphinxcontrib-serializinghtml = ">=1.1.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinxcontrib-websupport"]
|
||||
lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
|
||||
test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-applehelp"
|
||||
version = "1.0.2"
|
||||
description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
|
||||
{file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-devhelp"
|
||||
version = "1.0.2"
|
||||
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
|
||||
{file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-htmlhelp"
|
||||
version = "2.0.0"
|
||||
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"},
|
||||
{file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
test = ["html5lib", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-jsmath"
|
||||
version = "1.0.1"
|
||||
description = "A sphinx extension which renders display math in HTML via JavaScript"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
|
||||
{file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["flake8", "mypy", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-qthelp"
|
||||
version = "1.0.3"
|
||||
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
|
||||
{file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-serializinghtml"
|
||||
version = "1.1.5"
|
||||
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
|
||||
{file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.4.4"
|
||||
description = "A non-validating SQL parser."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
|
||||
{file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["build", "flake8"]
|
||||
doc = ["sphinx"]
|
||||
test = ["pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.5.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
|
||||
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.15"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||
files = [
|
||||
{file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
|
||||
{file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
|
||||
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "vine"
|
||||
version = "5.0.0"
|
||||
description = "Promises, promises, promises."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"},
|
||||
{file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.6"
|
||||
description = "Measures the displayed width of unicode strings in a terminal"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
|
||||
{file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.15.0"
|
||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
|
||||
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "1bdf2e39fdc05be7a0aaa245fd80ca653dd10dd480774577eb19d3c7d697f5e4"
|
31
pyproject.toml
Normal file
31
pyproject.toml
Normal file
|
@ -0,0 +1,31 @@
|
|||
[tool.poetry]
|
||||
name = "gvafile"
|
||||
version = "0.7.0"
|
||||
description = "GNUViech Admin fileserver administration tool"
|
||||
authors = ["Jan Dittberner <jan@dittberner.info>"]
|
||||
license = "AGPL-3.0+"
|
||||
readme = "README.rst"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7"
|
||||
celery = "^5.2.7"
|
||||
redis = "^4.5.1"
|
||||
importlib-metadata = "<5"
|
||||
gvacommon = {version = "^0.6.0", source = "gnuviech"}
|
||||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
sphinx = "<6"
|
||||
releases = "^2.0.0"
|
||||
coverage = "^7.1.0"
|
||||
|
||||
|
||||
[[tool.poetry.source]]
|
||||
name = "gnuviech"
|
||||
url = "https://pypi.gnuviech-server.de/simple"
|
||||
default = false
|
||||
secondary = false
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
|
@ -1,3 +0,0 @@
|
|||
# This file is here because many Platforms as a Service look for
|
||||
# requirements.txt in the root directory of a project.
|
||||
-r requirements/production.txt
|
|
@ -1,10 +0,0 @@
|
|||
amqp==1.4.6
|
||||
bpython==0.13.1
|
||||
anyjson==0.3.3
|
||||
argparse==1.2.1
|
||||
billiard==3.3.0.19
|
||||
celery==3.1.17
|
||||
kombu==3.0.24
|
||||
pytz==2014.10
|
||||
wsgiref==0.1.2
|
||||
PyYAML==3.11
|
|
@ -1,5 +0,0 @@
|
|||
# Local development dependencies go here
|
||||
-r base.txt
|
||||
coverage==3.7.1
|
||||
Sphinx==1.2.3
|
||||
releases==0.7.0
|
|
@ -1,3 +0,0 @@
|
|||
# Pro-tip: Try not to put anything here. There should be no dependency in
|
||||
# production that isn't in development.
|
||||
-r base.txt
|
|
@ -1,3 +0,0 @@
|
|||
# Test dependencies go here.
|
||||
-r base.txt
|
||||
coverage==3.7.1
|
12
salt/grains
Normal file
12
salt/grains
Normal file
|
@ -0,0 +1,12 @@
|
|||
gnuviechadmin:
|
||||
user: vagrant
|
||||
group: vagrant
|
||||
checkout: /vagrant
|
||||
home: /home/vagrant
|
||||
update_git: False
|
||||
roles:
|
||||
- vagrant
|
||||
- ldapclient
|
||||
- nfsserver
|
||||
- gnuviechadmin.gvafile
|
||||
|
11
salt/minion
Normal file
11
salt/minion
Normal file
|
@ -0,0 +1,11 @@
|
|||
file_client: local
|
||||
|
||||
file_roots:
|
||||
base:
|
||||
- /srv/salt/
|
||||
|
||||
pillar_roots:
|
||||
base:
|
||||
- /srv/pillar
|
||||
|
||||
log_file: file:///dev/log
|
Loading…
Reference in a new issue