From 31e0905e37ec365c89643246c4489fb6ab01e4ba Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Mar 19 2020 08:56:31 +0000 Subject: Add fedora-messaging schema and documentation. This commits adds the fedora-messaging message schema to the project and the boilerplate needed to generate the documentation. Signed-off-by: Clement Verna --- diff --git a/.gitignore b/.gitignore index fc576a5..f85434c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,9 @@ .venv # VS Code .vscode +# python +__pycache__ +*.egg-info + +#sphinx +build diff --git a/README.md b/README.md index e840468..bce510a 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,25 @@ $ source .venv/bin/activate (.venv) $ pip install poetry (.venv) $ poetry install ``` + +# Running the tests + +``` +$ poetry run pytest +``` + +# Building the docs + +Generate the json schema + +``` +$ cd docs +$ python generate_json_schema.py +``` + +Build the html + +``` +$ cd docs +$ make html +``` diff --git a/config.toml.example b/config.toml.example deleted file mode 100644 index eee7f09..0000000 --- a/config.toml.example +++ /dev/null @@ -1,18 +0,0 @@ -# A sample configuration for fedora-messaging. This file is in the TOML format. -# For complete details on all configuration options, see the documentation. - -amqp_url = "amqp://" - -publish_exchange = "amq.topic" - -# The topic_prefix configuration value will add a prefix to the topics of every sent message. -# This is used for migrating from fedmsg, and should not be used afterwards. -topic_prefix = "" - -[tls] -ca_cert = "/etc/pki/tls/certs/ca-bundle.crt" -keyfile = "/my/client/key.pem" -certfile = "/my/client/cert.pem" - -[client_properties] -app = "Koji" diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/generate_json_schema.py b/docs/generate_json_schema.py new file mode 100644 index 0000000..215a5ae --- /dev/null +++ b/docs/generate_json_schema.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 +# Copyright (C) 2020 Red Hat, Inc. +# +# This file was copied from Bodhi +# (https://github.com/fedora-infra/bodhi/blob/5.1.1/docs/generate_json_schema). +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +"""Generate JSON schema RST files.""" + +import json +import os + +from koji_fedmsg_plugin.messages import build, package, repo, rpm, tag, task + + +DOCS_DIR = os.path.dirname(os.path.realpath(__file__)) + + +for module in (build, package, repo, rpm, tag, task): + with open(f"{DOCS_DIR}/generated/{module.__name__.split('.')[-1]}.rst", 'w') as rst: + for attr in dir(module): + attr = getattr(module, attr) + if hasattr(attr, 'body_schema') and hasattr(attr, 'topic') and attr.topic: + indented_json = json.dumps(attr.body_schema, indent=4).replace('\n', '\n ') + rst.write(f"{attr.topic}\n{'-'*len(attr.topic)}\n::" + f'\n\n {indented_json}\n\n') diff --git a/docs/generated/build.rst b/docs/generated/build.rst new file mode 100644 index 0000000..bffe96b --- /dev/null +++ b/docs/generated/build.rst @@ -0,0 +1,81 @@ +buildsys.build.state.change +--------------------------- +:: + + { + "$id": "/v1/buildsys.build.state.change#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "The state of the build changed.", + "type": "object", + "properties": { + "build_id": { + "type": [ + "null", + "integer" + ], + "description": "build id" + }, + "old": { + "type": "integer", + "description": "previous state" + }, + "name": { + "type": "string", + "description": "name of the package built" + }, + "task_id": { + "type": [ + "null", + "integer" + ], + "description": "task id" + }, + "attribute": { + "type": "string", + "description": "attribute" + }, + "request": { + "type": [ + "null", + "array" + ], + "description": "build request details", + "contains": { + "type": "string" + } + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "epoch": { + "type": [ + "null", + "string", + "integer" + ], + "description": "epoch" + }, + "version": { + "type": "string", + "description": "version of the build" + }, + "owner": { + "type": [ + "null", + "integer", + "string" + ], + "description": "name of the package owner" + }, + "new": { + "type": "integer", + "description": "new state" + }, + "release": { + "type": "string", + "description": "release number of the package" + } + } + } + diff --git a/docs/generated/package.rst b/docs/generated/package.rst new file mode 100644 index 0000000..797cd2d --- /dev/null +++ b/docs/generated/package.rst @@ -0,0 +1,64 @@ +buildsys.package.list.change +---------------------------- +:: + + { + "$id": "/v1/buildsys.package.list.change#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package list changed.", + "type": "object", + "properties": { + "force": { + "type": [ + "null", + "boolean" + ], + "description": "force" + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "extra_arches": { + "type": [ + "null", + "string" + ], + "description": "extra arches" + }, + "package": { + "type": "string", + "description": "name of the package updated" + }, + "update": { + "type": [ + "null", + "boolean" + ], + "description": "update" + }, + "owner": { + "type": [ + "null", + "string" + ], + "description": "name of the package owner" + }, + "tag": { + "type": "string", + "description": "name of the tag" + }, + "action": { + "type": "string", + "description": "name of the action" + }, + "block": { + "type": [ + "null", + "boolean" + ], + "description": "block" + } + } + } + diff --git a/docs/generated/repo.rst b/docs/generated/repo.rst new file mode 100644 index 0000000..8626d67 --- /dev/null +++ b/docs/generated/repo.rst @@ -0,0 +1,58 @@ +buildsys.repo.done +------------------ +:: + + { + "$id": "/v1/buildsys.repo.done#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package repo task was done.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "repo_id": { + "type": "integer", + "description": "repo id" + }, + "tag": { + "type": "string", + "description": "tag used to generate the repo" + }, + "tag_id": { + "type": "integer", + "description": "tag id of the tag used to generate the repo" + } + } + } + +buildsys.repo.init +------------------ +:: + + { + "$id": "/v1/buildsys.repo.init#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package repo task is initialized.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji." + }, + "repo_id": { + "type": "integer", + "description": "repo id" + }, + "tag": { + "type": "string", + "description": "tag used to generate the repo" + }, + "tag_id": { + "type": "integer", + "description": "tag id of the tag used to generate the repo" + } + } + } + diff --git a/docs/generated/rpm.rst b/docs/generated/rpm.rst new file mode 100644 index 0000000..1aab0ef --- /dev/null +++ b/docs/generated/rpm.rst @@ -0,0 +1,224 @@ +buildsys.rpm.sign +----------------- +:: + + { + "$id": "/v1/buildsys.rpm.sign#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "An rpm build was signed by the build system.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "sigkey": { + "type": "string", + "description": "the signing key" + }, + "rpm": { + "type": "object", + "description": "An rpm build", + "properties": { + "build_id": { + "type": "integer", + "description": "koji build id" + }, + "name": { + "type": "string", + "description": "name of the rpm" + }, + "extra": { + "type": [ + "null", + "string" + ], + "description": "extra" + }, + "arch": { + "type": "string", + "description": "build architecture" + }, + "buildtime": { + "type": "integer", + "description": "build timestamp" + }, + "id": { + "type": "integer", + "description": "id" + }, + "epoch": { + "type": [ + "null", + "string", + "integer" + ], + "description": "epoch" + }, + "version": { + "type": "string", + "description": "rpm version" + }, + "metadata_only": { + "type": "boolean", + "description": "metadata only" + }, + "external_repo_id": { + "type": "integer", + "description": "external repo id" + }, + "release": { + "type": "string", + "description": "rpm release number" + }, + "size": { + "type": "integer", + "description": "size" + }, + "buildroot_id": { + "type": "integer", + "description": "buildroot id" + }, + "external_repo_name": { + "type": "string", + "description": "external_repo_name" + }, + "payloadhash": { + "type": "string", + "description": "payload hash" + } + } + }, + "build": { + "type": "object", + "description": "build details", + "properties": { + "cg_id": { + "type": [ + "null", + "integer", + "string" + ], + "description": "cg id" + }, + "package_name": { + "type": "string", + "description": "package name" + }, + "extra": { + "type": "object", + "description": "extra", + "properties": { + "source": { + "type": "object", + "description": "build source", + "properties": { + "original_url": { + "type": "string", + "description": "dist git url" + } + } + } + } + }, + "creation_time": { + "type": "number", + "description": "koji build creation time" + }, + "completion_time": { + "type": "number", + "description": "koji build completion time" + }, + "package_id": { + "type": "integer", + "description": "package id" + }, + "cg_name": { + "type": [ + "null", + "integer", + "string" + ], + "description": "cg name" + }, + "id": { + "type": "integer", + "description": "id" + }, + "build_id": { + "type": "integer", + "description": "build id" + }, + "epoch": { + "type": [ + "null", + "integer", + "string" + ], + "description": "epoch" + }, + "source": { + "type": "string", + "description": "dist git url" + }, + "state": { + "type": "integer", + "description": "koji build state" + }, + "version": { + "type": "string", + "description": "rpm version" + }, + "owner_id": { + "type": "integer", + "description": "owner id" + }, + "owner_name": { + "type": "string", + "description": "owner name" + }, + "nvr": { + "type": "string", + "description": "rpm name version release" + }, + "start_time": { + "type": "integer", + "description": "build start time" + }, + "creation_event_id": { + "type": "integer", + "description": "creation event id" + }, + "volume_id": { + "type": "integer", + "description": "volume id" + }, + "creation_ts": { + "type": "number", + "description": "creation timestamp" + }, + "name": { + "type": "string", + "description": "name" + }, + "task_id": { + "type": "integer", + "description": "koji task id" + }, + "volume_name": { + "type": "string", + "description": "volume name" + }, + "release": { + "type": "string", + "description": "rpm release number" + } + } + }, + "sighash": { + "type": "string", + "description": "signing hash" + } + } + } + diff --git a/docs/generated/tag.rst b/docs/generated/tag.rst new file mode 100644 index 0000000..2ba27ab --- /dev/null +++ b/docs/generated/tag.rst @@ -0,0 +1,98 @@ +buildsys.tag +------------ +:: + + { + "$id": "/v1/buildsys.tag#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package is tagged.", + "type": "object", + "properties": { + "build_id": { + "type": "integer", + "description": "build id" + }, + "name": { + "type": "string", + "description": "package name" + }, + "tag_id": { + "type": "integer", + "description": "tag id" + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "tag": { + "type": "string", + "description": "name of the tag" + }, + "user": { + "type": "string", + "description": "name of the user that trigger the build" + }, + "version": { + "type": "string", + "description": "version of the build" + }, + "owner": { + "type": "string", + "description": "name of the package owner" + }, + "release": { + "type": "string", + "description": "release number of the package" + } + } + } + +buildsys.untag +-------------- +:: + + { + "$id": "/v1/buildsys.untag#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package is untagged.", + "type": "object", + "properties": { + "build_id": { + "type": "integer", + "description": "build id" + }, + "name": { + "type": "string", + "description": "package name" + }, + "tag_id": { + "type": "integer", + "description": "tag id" + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "tag": { + "type": "string", + "description": "name of the tag" + }, + "user": { + "type": "string", + "description": "name of the user that trigger the build" + }, + "version": { + "type": "string", + "description": "version of the build" + }, + "owner": { + "type": "string", + "description": "name of the package owner" + }, + "release": { + "type": "string", + "description": "release number of the package" + } + } + } + diff --git a/docs/generated/task.rst b/docs/generated/task.rst new file mode 100644 index 0000000..0b0894a --- /dev/null +++ b/docs/generated/task.rst @@ -0,0 +1,139 @@ +buildsys.task.state.change +-------------------------- +:: + + { + "$id": "/v1/buildsys.task.state.change#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A koji task state changed.", + "type": "object", + "properties": { + "info": { + "type": "object", + "description": "task info", + "properties": { + "parent": { + "type": [ + "null", + "array" + ], + "description": "parent tasks" + }, + "completion_time": { + "type": "number", + "description": "completion time" + }, + "start_time": { + "type": "number", + "description": "start time" + }, + "request": { + "type": [ + "null", + "array" + ], + "description": "task request details", + "contains": { + "type": "string" + } + }, + "waiting": { + "type": "boolean", + "description": "Is the task waiting or not" + }, + "awaited": { + "type": "null", + "description": "awaited" + }, + "id": { + "type": "integer", + "description": "id" + }, + "priority": { + "type": "integer", + "description": "priority" + }, + "channel_id": { + "type": "integer", + "description": "channel_id" + }, + "state": { + "type": "integer", + "description": "task state" + }, + "create_time": { + "type": "number", + "description": "create time" + }, + "result": { + "type": "null", + "description": "result" + }, + "owner": { + "type": [ + "null", + "string", + "integer" + ], + "description": "owner name or id" + }, + "host_id": { + "type": "integer", + "description": "host id" + }, + "method": { + "type": "string", + "description": "task method" + }, + "label": { + "type": "null", + "description": "label" + }, + "arch": { + "type": "string", + "description": "task specific architecture" + }, + "children": { + "type": [ + "null", + "array" + ], + "description": "task childrens" + } + } + }, + "old": { + "type": "string", + "description": "previous task state" + }, + "attribute": { + "type": "string", + "description": "attribute" + }, + "id": { + "type": "integer", + "description": "task id" + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji" + }, + "owner": { + "type": "string", + "description": "name of the package owner" + }, + "new": { + "type": "string", + "description": "name of the new task state" + }, + "srpm": { + "type": "string", + "description": "name of the source rpm" + }, + "method": { + "type": "string", + "description": "name of the task method" + } + } + } + diff --git a/docs/source/build.rst b/docs/source/build.rst new file mode 100644 index 0000000..1520d58 --- /dev/null +++ b/docs/source/build.rst @@ -0,0 +1,18 @@ +============== +Build Messages +============== + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.build + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/build.rst diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..fe2d749 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,58 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# 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. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'koji-fedmsg-plugin' +copyright = '2020, Fedora Infrastructure' +author = 'Fedora Infrastructure' + +# The full version, including alpha/beta/rc tags +release = '0.1.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +master_doc = 'index' + +# -- 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 = 'alabaster' + +# 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'] diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..6476fa7 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,30 @@ +.. koji-fedmsg-plugin documentation master file, created by + sphinx-quickstart on Thu Mar 19 08:49:31 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to koji-fedmsg-plugin's documentation! +============================================== + +This project defines `fedora-messages` sent by Fedora's build system koji. + +Included in this library are the message schema for those messages, and a handy Python class that +can be used to send and receive those messages. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + build + package + repo + rpm + tag + task + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/package.rst b/docs/source/package.rst new file mode 100644 index 0000000..5efac96 --- /dev/null +++ b/docs/source/package.rst @@ -0,0 +1,18 @@ +================ +Package Messages +================ + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.package + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/package.rst diff --git a/docs/source/repo.rst b/docs/source/repo.rst new file mode 100644 index 0000000..5b2e0f4 --- /dev/null +++ b/docs/source/repo.rst @@ -0,0 +1,18 @@ +============= +Repo Messages +============= + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.repo + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/repo.rst diff --git a/docs/source/rpm.rst b/docs/source/rpm.rst new file mode 100644 index 0000000..386c175 --- /dev/null +++ b/docs/source/rpm.rst @@ -0,0 +1,18 @@ +============ +RPM Messages +============ + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.rpm + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/rpm.rst diff --git a/docs/source/tag.rst b/docs/source/tag.rst new file mode 100644 index 0000000..6acef25 --- /dev/null +++ b/docs/source/tag.rst @@ -0,0 +1,18 @@ +============ +Tag Messages +============ + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.tag + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/tag.rst diff --git a/docs/source/task.rst b/docs/source/task.rst new file mode 100644 index 0000000..78e2076 --- /dev/null +++ b/docs/source/task.rst @@ -0,0 +1,18 @@ +============= +Task Messages +============= + +Python objects +============== + +.. automodule:: koji_fedmsg_plugin.messages.task + :exclude-members: body_schema, __module__ + :members: + :special-members: + :show-inheritance: + :undoc-members: + +JSON schemas +============ + +.. include:: ../generated/task.rst diff --git a/fedmsg-koji-plugin.py b/fedmsg-koji-plugin.py deleted file mode 100644 index c645349..0000000 --- a/fedmsg-koji-plugin.py +++ /dev/null @@ -1,260 +0,0 @@ -# Koji callback for sending notifications about events to the fedmsg message bus -# Copyright (c) 2009-2019 Red Hat, Inc. -# -# Source: https://pagure.io/koji-fedmsg-plugin/ -# -# Authors: -# Ralph Bean -# Mike Bonnet - -import logging -import re -import time - -from koji.context import context -from koji.plugin import callbacks -from koji.plugin import callback -from koji.plugin import ignore_error -import fedora_messaging.api -import fedora_messaging.exceptions -import kojihub - - -MAX_KEY_LENGTH = 255 -log = logging.getLogger(__name__) - - -def camel_to_dots(name): - s1 = re.sub('(.)([A-Z][a-z]+)', r'\1.\2', name) - return re.sub('([a-z0-9])([A-Z])', r'\1.\2', s1).lower() - - -def serialize_datetime_in_task(task): - date_fields = [ - "completion_time", "create_time", "start_time", "buildtime", - "creation_ts", "creation_time", - ] - for date_key in date_fields: - if task.get(date_key) is None: - continue - if isinstance(task[date_key], (float, int, long)): - continue - task[date_key] = time.mktime(task[date_key].timetuple()) - - -def get_message_body(topic, *args, **kws): - msg = {} - - if topic == 'package.list.change': - msg['tag'] = kws['tag']['name'] - msg['package'] = kws['package']['name'] - msg['action'] = kws['action'] - if 'owner' in kws: - msg['owner'] = kojihub.get_user(kws['owner'])['name'] - else: - msg['owner'] = None - msg['block'] = kws.get('block', None) - msg['extra_arches'] = kws.get('extra_arches', None) - msg['force'] = kws.get('force', None) - msg['update'] = kws.get('update', None) - elif topic == 'task.state.change': - info = kws['info'] - serialize_datetime_in_task(info) - - # Stuff in information about descendant tasks - task = kojihub.Task(info['id']) - info['children'] = [] - for child_orig in task.getChildren(): - child = child_orig.copy() - serialize_datetime_in_task(child) - info['children'].append(child) - - # Send the whole info dict along because it might have useful info. - # For instance, it contains the mention of what format createAppliance - # is using (raw or qcow2). - msg['info'] = info - msg['method'] = kws['info']['method'] - msg['attribute'] = kws['attribute'] - msg['old'] = kws['old'] - msg['new'] = kws['new'] - msg['id'] = kws['info']['id'] - - # extract a useful identifier from the request string - request = kws.get('info', {}).get('request', ['/']) - msg['srpm'] = request[0].split('/')[-1] - - if 'owner_name' in info: - msg['owner'] = info['owner_name'] - elif 'owner_id' in info: - msg['owner'] = kojihub.get_user(info['owner_id'])['name'] - elif 'owner' in info: - msg['owner'] = kojihub.get_user(info['owner'])['name'] - else: - msg['owner'] = None - - elif topic == 'build.state.change': - info = kws['info'] - msg['name'] = info['name'] - msg['version'] = info['version'] - msg['release'] = info['release'] - msg['epoch'] = info.get('epoch') - msg['attribute'] = kws['attribute'] - msg['old'] = kws['old'] - msg['new'] = kws['new'] - msg['build_id'] = info.get('id', None) - msg['task_id'] = info.get('task_id', None) - - if msg['task_id']: - task = kojihub.Task(msg['task_id']) - msg['request'] = task.getRequest() - else: - msg['request'] = None - - if 'owner_name' in info: - msg['owner'] = info['owner_name'] - elif 'owner_id' in info: - msg['owner'] = kojihub.get_user(info['owner_id'])['name'] - elif 'owner' in info: - msg['owner'] = kojihub.get_user(info['owner'])['name'] - else: - msg['owner'] = None - - elif topic == 'import': - # TODO -- import is currently unused. - # Should we remove it? - msg['type'] = kws['type'] - elif topic in ('tag', 'untag'): - msg['tag'] = kws['tag']['name'] - build = kws['build'] - msg['name'] = build['name'] - msg['version'] = build['version'] - msg['release'] = build['release'] - msg['user'] = kws['user']['name'] - msg['owner'] = kojihub.get_user(kws['build']['owner_id'])['name'] - msg['tag_id'] = kws['tag']['id'] - msg['build_id'] = kws['build']['id'] - elif topic == 'repo.init': - msg['tag'] = kws['tag']['name'] - msg['tag_id'] = kws['tag']['id'] - msg['repo_id'] = kws['repo_id'] - elif topic == 'repo.done': - msg['tag'] = kws['repo']['tag_name'] - msg['tag_id'] = kws['repo']['tag_id'] - msg['repo_id'] = kws['repo']['id'] - elif topic == 'rpm.sign': - if 'attribute' in kws: - # v1.10.1 and earlier - msg['attribute'] = kws['attribute'] - msg['old'] = kws['old'] - msg['new'] = kws['new'] - msg['info'] = kws['info'] - else: - # v1.11.0 (and maybe higher, but who knows) - msg['sigkey'] = kws['sigkey'] - msg['sighash'] = kws['sighash'] - msg['build'] = kws['build'] - msg['rpm'] = kws['rpm'] - serialize_datetime_in_task(msg['build']) - serialize_datetime_in_task(msg['rpm']) - - return msg - - -# This callback gets run for every koji event that starts with "post" -@callback(*[ - c for c in callbacks.keys() - if c.startswith('post') and c not in [ - 'postImport', # This is kind of useless; also noisy. - # This one is special, and is called every time, so ignore it. - # Added here https://pagure.io/koji/pull-request/148 - 'postCommit', - ] -]) -@ignore_error -def queue_message(cbtype, *args, **kws): - if cbtype.startswith('post'): - msgtype = cbtype[4:] - else: - msgtype = cbtype[3:] - - # Short-circuit ourselves for task events. They are very spammy and we are - # only interested in state changes to scratch builds (parent tasks). - if cbtype == 'postTaskStateChange': - # only state changes - if not kws.get('attribute', None) == 'state': - return - # only parent tasks - if kws.get('info', {}).get('parent'): - return - # only scratch builds - request = kws.get('info', {}).get('request', [{}])[-1] - if not isinstance(request, dict) or not request.get('scratch'): - return - - topic = camel_to_dots(msgtype) - body = get_message_body(topic, *args, **kws) - - # We need this to distinguish between messages from primary koji - # and the secondary hubs off for s390 and ppc. - body['instance'] = 'primary' - - # Don't publish these uninformative rpm.sign messages if there's no actual - # sigkey present. Koji apparently adds a dummy sig value when rpms are - # first imported and there's no need to spam the world about that. - if topic == 'rpm.sign' and (body.get('info', {}).get('sigkey') == '' or - body.get('sigkey') == ''): - return - - # Also, do not want to send a message on volume_id changes - if topic == 'build.state.change' and body.get('attribute') == 'volume_id': - return - - # Last thing to do before publishing: scrub some problematic fields - # These fields are floating points which get json-encoded differently on - # rhel and fedora. - problem_fields = ['weight', 'start_ts', 'create_ts', 'completion_ts'] - - def scrub(obj): - if isinstance(obj, list): - return [scrub(item) for item in obj] - if isinstance(obj, dict): - return dict([ - (k, scrub(v)) - for k, v in obj.items() - if k not in problem_fields - ]) - return obj - - body = scrub(body) - - # Queue the message for later. - # It will only get sent after postCommit is called. - messages = getattr(context, 'fedmsg_plugin_messages', []) - messages.append(dict(topic=topic, msg=body)) - context.fedmsg_plugin_messages = messages - - -# Meanwhile, postCommit actually sends messages. -@callback('postCommit') -@ignore_error -def send_messages(cbtype, *args, **kws): - messages = getattr(context, 'fedmsg_plugin_messages', []) - - for message in messages: - try: - topic = "buildsys.{}".format(message['topic']) - msg = fedora_messaging.api.Message( - topic=topic, - body=message['msg'] - ) - log.info("Publishing message on topic {}".format(topic)) - log.debug("Message body {}".format(message['msg'])) - fedora_messaging.api.publish(msg) - except fedora_messaging.exceptions.PublishReturned as e: - log.warning( - "Fedora Messaging broker rejected message %s: %s", msg.id, e - ) - except fedora_messaging.exceptions.ConnectionException as e: - log.warning("Error sending message %s: %s", msg.id, e) - except Exception: - log.exception("Un-expected error sending fedora-messaging message") diff --git a/koji_fedmsg_plugin/__init__.py b/koji_fedmsg_plugin/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/koji_fedmsg_plugin/__init__.py diff --git a/koji_fedmsg_plugin/config.toml.example b/koji_fedmsg_plugin/config.toml.example new file mode 100644 index 0000000..eee7f09 --- /dev/null +++ b/koji_fedmsg_plugin/config.toml.example @@ -0,0 +1,18 @@ +# A sample configuration for fedora-messaging. This file is in the TOML format. +# For complete details on all configuration options, see the documentation. + +amqp_url = "amqp://" + +publish_exchange = "amq.topic" + +# The topic_prefix configuration value will add a prefix to the topics of every sent message. +# This is used for migrating from fedmsg, and should not be used afterwards. +topic_prefix = "" + +[tls] +ca_cert = "/etc/pki/tls/certs/ca-bundle.crt" +keyfile = "/my/client/key.pem" +certfile = "/my/client/cert.pem" + +[client_properties] +app = "Koji" diff --git a/koji_fedmsg_plugin/koji-fedmsg-plugin.py b/koji_fedmsg_plugin/koji-fedmsg-plugin.py new file mode 100644 index 0000000..c645349 --- /dev/null +++ b/koji_fedmsg_plugin/koji-fedmsg-plugin.py @@ -0,0 +1,260 @@ +# Koji callback for sending notifications about events to the fedmsg message bus +# Copyright (c) 2009-2019 Red Hat, Inc. +# +# Source: https://pagure.io/koji-fedmsg-plugin/ +# +# Authors: +# Ralph Bean +# Mike Bonnet + +import logging +import re +import time + +from koji.context import context +from koji.plugin import callbacks +from koji.plugin import callback +from koji.plugin import ignore_error +import fedora_messaging.api +import fedora_messaging.exceptions +import kojihub + + +MAX_KEY_LENGTH = 255 +log = logging.getLogger(__name__) + + +def camel_to_dots(name): + s1 = re.sub('(.)([A-Z][a-z]+)', r'\1.\2', name) + return re.sub('([a-z0-9])([A-Z])', r'\1.\2', s1).lower() + + +def serialize_datetime_in_task(task): + date_fields = [ + "completion_time", "create_time", "start_time", "buildtime", + "creation_ts", "creation_time", + ] + for date_key in date_fields: + if task.get(date_key) is None: + continue + if isinstance(task[date_key], (float, int, long)): + continue + task[date_key] = time.mktime(task[date_key].timetuple()) + + +def get_message_body(topic, *args, **kws): + msg = {} + + if topic == 'package.list.change': + msg['tag'] = kws['tag']['name'] + msg['package'] = kws['package']['name'] + msg['action'] = kws['action'] + if 'owner' in kws: + msg['owner'] = kojihub.get_user(kws['owner'])['name'] + else: + msg['owner'] = None + msg['block'] = kws.get('block', None) + msg['extra_arches'] = kws.get('extra_arches', None) + msg['force'] = kws.get('force', None) + msg['update'] = kws.get('update', None) + elif topic == 'task.state.change': + info = kws['info'] + serialize_datetime_in_task(info) + + # Stuff in information about descendant tasks + task = kojihub.Task(info['id']) + info['children'] = [] + for child_orig in task.getChildren(): + child = child_orig.copy() + serialize_datetime_in_task(child) + info['children'].append(child) + + # Send the whole info dict along because it might have useful info. + # For instance, it contains the mention of what format createAppliance + # is using (raw or qcow2). + msg['info'] = info + msg['method'] = kws['info']['method'] + msg['attribute'] = kws['attribute'] + msg['old'] = kws['old'] + msg['new'] = kws['new'] + msg['id'] = kws['info']['id'] + + # extract a useful identifier from the request string + request = kws.get('info', {}).get('request', ['/']) + msg['srpm'] = request[0].split('/')[-1] + + if 'owner_name' in info: + msg['owner'] = info['owner_name'] + elif 'owner_id' in info: + msg['owner'] = kojihub.get_user(info['owner_id'])['name'] + elif 'owner' in info: + msg['owner'] = kojihub.get_user(info['owner'])['name'] + else: + msg['owner'] = None + + elif topic == 'build.state.change': + info = kws['info'] + msg['name'] = info['name'] + msg['version'] = info['version'] + msg['release'] = info['release'] + msg['epoch'] = info.get('epoch') + msg['attribute'] = kws['attribute'] + msg['old'] = kws['old'] + msg['new'] = kws['new'] + msg['build_id'] = info.get('id', None) + msg['task_id'] = info.get('task_id', None) + + if msg['task_id']: + task = kojihub.Task(msg['task_id']) + msg['request'] = task.getRequest() + else: + msg['request'] = None + + if 'owner_name' in info: + msg['owner'] = info['owner_name'] + elif 'owner_id' in info: + msg['owner'] = kojihub.get_user(info['owner_id'])['name'] + elif 'owner' in info: + msg['owner'] = kojihub.get_user(info['owner'])['name'] + else: + msg['owner'] = None + + elif topic == 'import': + # TODO -- import is currently unused. + # Should we remove it? + msg['type'] = kws['type'] + elif topic in ('tag', 'untag'): + msg['tag'] = kws['tag']['name'] + build = kws['build'] + msg['name'] = build['name'] + msg['version'] = build['version'] + msg['release'] = build['release'] + msg['user'] = kws['user']['name'] + msg['owner'] = kojihub.get_user(kws['build']['owner_id'])['name'] + msg['tag_id'] = kws['tag']['id'] + msg['build_id'] = kws['build']['id'] + elif topic == 'repo.init': + msg['tag'] = kws['tag']['name'] + msg['tag_id'] = kws['tag']['id'] + msg['repo_id'] = kws['repo_id'] + elif topic == 'repo.done': + msg['tag'] = kws['repo']['tag_name'] + msg['tag_id'] = kws['repo']['tag_id'] + msg['repo_id'] = kws['repo']['id'] + elif topic == 'rpm.sign': + if 'attribute' in kws: + # v1.10.1 and earlier + msg['attribute'] = kws['attribute'] + msg['old'] = kws['old'] + msg['new'] = kws['new'] + msg['info'] = kws['info'] + else: + # v1.11.0 (and maybe higher, but who knows) + msg['sigkey'] = kws['sigkey'] + msg['sighash'] = kws['sighash'] + msg['build'] = kws['build'] + msg['rpm'] = kws['rpm'] + serialize_datetime_in_task(msg['build']) + serialize_datetime_in_task(msg['rpm']) + + return msg + + +# This callback gets run for every koji event that starts with "post" +@callback(*[ + c for c in callbacks.keys() + if c.startswith('post') and c not in [ + 'postImport', # This is kind of useless; also noisy. + # This one is special, and is called every time, so ignore it. + # Added here https://pagure.io/koji/pull-request/148 + 'postCommit', + ] +]) +@ignore_error +def queue_message(cbtype, *args, **kws): + if cbtype.startswith('post'): + msgtype = cbtype[4:] + else: + msgtype = cbtype[3:] + + # Short-circuit ourselves for task events. They are very spammy and we are + # only interested in state changes to scratch builds (parent tasks). + if cbtype == 'postTaskStateChange': + # only state changes + if not kws.get('attribute', None) == 'state': + return + # only parent tasks + if kws.get('info', {}).get('parent'): + return + # only scratch builds + request = kws.get('info', {}).get('request', [{}])[-1] + if not isinstance(request, dict) or not request.get('scratch'): + return + + topic = camel_to_dots(msgtype) + body = get_message_body(topic, *args, **kws) + + # We need this to distinguish between messages from primary koji + # and the secondary hubs off for s390 and ppc. + body['instance'] = 'primary' + + # Don't publish these uninformative rpm.sign messages if there's no actual + # sigkey present. Koji apparently adds a dummy sig value when rpms are + # first imported and there's no need to spam the world about that. + if topic == 'rpm.sign' and (body.get('info', {}).get('sigkey') == '' or + body.get('sigkey') == ''): + return + + # Also, do not want to send a message on volume_id changes + if topic == 'build.state.change' and body.get('attribute') == 'volume_id': + return + + # Last thing to do before publishing: scrub some problematic fields + # These fields are floating points which get json-encoded differently on + # rhel and fedora. + problem_fields = ['weight', 'start_ts', 'create_ts', 'completion_ts'] + + def scrub(obj): + if isinstance(obj, list): + return [scrub(item) for item in obj] + if isinstance(obj, dict): + return dict([ + (k, scrub(v)) + for k, v in obj.items() + if k not in problem_fields + ]) + return obj + + body = scrub(body) + + # Queue the message for later. + # It will only get sent after postCommit is called. + messages = getattr(context, 'fedmsg_plugin_messages', []) + messages.append(dict(topic=topic, msg=body)) + context.fedmsg_plugin_messages = messages + + +# Meanwhile, postCommit actually sends messages. +@callback('postCommit') +@ignore_error +def send_messages(cbtype, *args, **kws): + messages = getattr(context, 'fedmsg_plugin_messages', []) + + for message in messages: + try: + topic = "buildsys.{}".format(message['topic']) + msg = fedora_messaging.api.Message( + topic=topic, + body=message['msg'] + ) + log.info("Publishing message on topic {}".format(topic)) + log.debug("Message body {}".format(message['msg'])) + fedora_messaging.api.publish(msg) + except fedora_messaging.exceptions.PublishReturned as e: + log.warning( + "Fedora Messaging broker rejected message %s: %s", msg.id, e + ) + except fedora_messaging.exceptions.ConnectionException as e: + log.warning("Error sending message %s: %s", msg.id, e) + except Exception: + log.exception("Un-expected error sending fedora-messaging message") diff --git a/koji_fedmsg_plugin/messages/__init__.py b/koji_fedmsg_plugin/messages/__init__.py new file mode 100644 index 0000000..9b80e6c --- /dev/null +++ b/koji_fedmsg_plugin/messages/__init__.py @@ -0,0 +1,14 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" diff --git a/koji_fedmsg_plugin/messages/build.py b/koji_fedmsg_plugin/messages/build.py new file mode 100644 index 0000000..2a9165e --- /dev/null +++ b/koji_fedmsg_plugin/messages/build.py @@ -0,0 +1,104 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" +from typing import List, Optional, Any + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class BuildStateChangeV1(message.Message): + """ This message is sent when a build state changes. """ + + topic = "buildsys.build.state.change" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "The state of the build changed.", + "type": "object", + "properties": { + "build_id": {"type": ["null", "integer"], "description": "build id"}, + "old": {"type": "integer", "description": "previous state"}, + "name": {"type": "string", "description": "name of the package built",}, + "task_id": {"type": ["null", "integer"], "description": "task id",}, + "attribute": {"type": "string", "description": "attribute",}, + "request": { + "type": ["null", "array"], + "description": "build request details", + "contains": {"type": "string"}, + }, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "epoch": {"type": ["null", "string", "integer"], "description": "epoch",}, + "version": {"type": "string", "description": "version of the build",}, + "owner": { + "type": ["null", "integer", "string"], + "description": "name of the package owner", + }, + "new": {"type": "integer", "description": "new state",}, + "release": {"type": "string", "description": "release number of the package",}, + }, + } + + @property + def build_id(self) -> Optional[int]: + return self.body["build_id"] + + @property + def old(self) -> int: + return self.body["old"] + + @property + def name(self) -> str: + return self.body["name"] + + @property + def task_id(self) -> Optional[int]: + return self.body["task_id"] + + @property + def attribute(self) -> str: + return self.body["attribute"] + + @property + def request(self) -> Optional[List]: + return self.body["request"] + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def version(self) -> str: + return self.body["version"] + + @property + def owner(self) -> str: + return self.body["owner"] + + @property + def new(self) -> int: + return self.body["new"] + + @property + def release(self) -> str: + return self.body["release"] + + @property + def epoch(self) -> Any: + return self.body["epoch"] diff --git a/koji_fedmsg_plugin/messages/package.py b/koji_fedmsg_plugin/messages/package.py new file mode 100644 index 0000000..c8aa775 --- /dev/null +++ b/koji_fedmsg_plugin/messages/package.py @@ -0,0 +1,82 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" +from typing import Optional + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class ListChangeV1(message.Message): + """ This message is sent when a package list changes. """ + + topic = "buildsys.package.list.change" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package list changed.", + "type": "object", + "properties": { + "force": {"type": ["null", "boolean"], "description": "force"}, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "extra_arches": {"type": ["null", "string"], "description": "extra arches"}, + "package": {"type": "string", "description": "name of the package updated",}, + "update": {"type": ["null", "boolean"], "description": "update",}, + "owner": {"type": ["null", "string"], "description": "name of the package owner",}, + "tag": {"type": "string", "description": "name of the tag",}, + "action": {"type": "string", "description": "name of the action",}, + "block": {"type": ["null", "boolean"], "description": "block"}, + }, + } + + @property + def force(self) -> Optional[bool]: + return self.body["force"] + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def extra_arches(self) -> Optional[str]: + return self.body["extra_arches"] + + @property + def package(self) -> str: + return self.body["package"] + + @property + def update(self) -> Optional[bool]: + return self.body["update"] + + @property + def owner(self) -> Optional[str]: + return self.body["owner"] + + @property + def tag(self) -> str: + return self.body["tag"] + + @property + def action(self) -> str: + return self.body["action"] + + @property + def block(self) -> Optional[bool]: + return self.body["block"] diff --git a/koji_fedmsg_plugin/messages/repo.py b/koji_fedmsg_plugin/messages/repo.py new file mode 100644 index 0000000..06b3211 --- /dev/null +++ b/koji_fedmsg_plugin/messages/repo.py @@ -0,0 +1,101 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" + + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class DoneV1(message.Message): + """ This message is sent when a package repo is done. """ + + topic = "buildsys.repo.done" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package repo task was done.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "repo_id": {"type": "integer", "description": "repo id"}, + "tag": {"type": "string", "description": "tag used to generate the repo",}, + "tag_id": { + "type": "integer", + "description": "tag id of the tag used to generate the repo", + }, + }, + } + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def repo_id(self) -> int: + return self.body["repo_id"] + + @property + def tag(self) -> str: + return self.body["tag"] + + @property + def tag_id(self) -> int: + return self.body["tag_id"] + + +class InitV1(message.Message): + """ This message is sent when a package repo is initialized. """ + + topic = "buildsys.repo.init" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package repo task is initialized.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji.", + }, + "repo_id": {"type": "integer", "description": "repo id"}, + "tag": {"type": "string", "description": "tag used to generate the repo",}, + "tag_id": { + "type": "integer", + "description": "tag id of the tag used to generate the repo", + }, + }, + } + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def repo_id(self) -> int: + return self.body["repo_id"] + + @property + def tag(self) -> str: + return self.body["tag"] + + @property + def tag_id(self) -> int: + return self.body["tag_id"] diff --git a/koji_fedmsg_plugin/messages/rpm.py b/koji_fedmsg_plugin/messages/rpm.py new file mode 100644 index 0000000..a20eeb3 --- /dev/null +++ b/koji_fedmsg_plugin/messages/rpm.py @@ -0,0 +1,129 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" + + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class SignV1(message.Message): + """ This message is sent when a rpm is signed. """ + + topic = "buildsys.rpm.sign" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "An rpm build was signed by the build system.", + "type": "object", + "properties": { + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "sigkey": {"type": "string", "description": "the signing key"}, + "rpm": { + "type": "object", + "description": "An rpm build", + "properties": { + "build_id": {"type": "integer", "description": "koji build id"}, + "name": {"type": "string", "description": "name of the rpm"}, + "extra": {"type": ["null", "string"], "description": "extra",}, + "arch": {"type": "string", "description": "build architecture",}, + "buildtime": {"type": "integer", "description": "build timestamp",}, + "id": {"type": "integer", "description": "id",}, + "epoch": {"type": ["null", "string", "integer"], "description": "epoch",}, + "version": {"type": "string", "description": "rpm version",}, + "metadata_only": {"type": "boolean", "description": "metadata only",}, + "external_repo_id": {"type": "integer", "description": "external repo id",}, + "release": {"type": "string", "description": "rpm release number",}, + "size": {"type": "integer", "description": "size",}, + "buildroot_id": {"type": "integer", "description": "buildroot id",}, + "external_repo_name": {"type": "string", "description": "external_repo_name",}, + "payloadhash": {"type": "string", "description": "payload hash",}, + }, + }, + "build": { + "type": "object", + "description": "build details", + "properties": { + "cg_id": {"type": ["null", "integer", "string"], "description": "cg id",}, + "package_name": {"type": "string", "description": "package name",}, + "extra": { + "type": "object", + "description": "extra", + "properties": { + "source": { + "type": "object", + "description": "build source", + "properties": { + "original_url": { + "type": "string", + "description": "dist git url", + }, + }, + }, + }, + }, + "creation_time": {"type": "number", "description": "koji build creation time",}, + "completion_time": { + "type": "number", + "description": "koji build completion time", + }, + "package_id": {"type": "integer", "description": "package id",}, + "cg_name": {"type": ["null", "integer", "string"], "description": "cg name",}, + "id": {"type": "integer", "description": "id",}, + "build_id": {"type": "integer", "description": "build id",}, + "epoch": {"type": ["null", "integer", "string"], "description": "epoch",}, + "source": {"type": "string", "description": "dist git url",}, + "state": {"type": "integer", "description": "koji build state",}, + "version": {"type": "string", "description": "rpm version",}, + "owner_id": {"type": "integer", "description": "owner id",}, + "owner_name": {"type": "string", "description": "owner name",}, + "nvr": {"type": "string", "description": "rpm name version release",}, + "start_time": {"type": "integer", "description": "build start time",}, + "creation_event_id": {"type": "integer", "description": "creation event id",}, + "volume_id": {"type": "integer", "description": "volume id",}, + "creation_ts": {"type": "number", "description": "creation timestamp",}, + "name": {"type": "string", "description": "name",}, + "task_id": {"type": "integer", "description": "koji task id",}, + "volume_name": {"type": "string", "description": "volume name",}, + "release": {"type": "string", "description": "rpm release number",}, + }, + }, + "sighash": {"type": "string", "description": "signing hash",}, + }, + } + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def sigkey(self) -> str: + return self.body["sigkey"] + + @property + def rpm(self) -> dict: + return self.body["rpm"] + + @property + def build(self) -> dict: + return self.body["build"] + + @property + def sighash(self) -> str: + return self.body["sighash"] diff --git a/koji_fedmsg_plugin/messages/tag.py b/koji_fedmsg_plugin/messages/tag.py new file mode 100644 index 0000000..9a1e3fc --- /dev/null +++ b/koji_fedmsg_plugin/messages/tag.py @@ -0,0 +1,145 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" + + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class TagV1(message.Message): + """ This message is sent when a package is tagged. """ + + topic = "buildsys.tag" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package is tagged.", + "type": "object", + "properties": { + "build_id": {"type": "integer", "description": "build id"}, + "name": {"type": "string", "description": "package name"}, + "tag_id": {"type": "integer", "description": "tag id",}, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "tag": {"type": "string", "description": "name of the tag",}, + "user": {"type": "string", "description": "name of the user that trigger the build",}, + "version": {"type": "string", "description": "version of the build",}, + "owner": {"type": "string", "description": "name of the package owner",}, + "release": {"type": "string", "description": "release number of the package",}, + }, + } + + @property + def build_id(self) -> int: + return self.body["build_id"] + + @property + def name(self) -> str: + return self.body["name"] + + @property + def tag_id(self) -> int: + return self.body["tag_id"] + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def tag(self) -> str: + return self.body["tag"] + + @property + def user(self) -> str: + return self.body["user"] + + @property + def version(self) -> str: + return self.body["version"] + + @property + def owner(self) -> str: + return self.body["owner"] + + @property + def release(self) -> str: + return self.body["release"] + + +class UntagV1(message.Message): + """ This message is sent when a package is untagged. """ + + topic = "buildsys.untag" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A package is untagged.", + "type": "object", + "properties": { + "build_id": {"type": "integer", "description": "build id"}, + "name": {"type": "string", "description": "package name"}, + "tag_id": {"type": "integer", "description": "tag id",}, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "tag": {"type": "string", "description": "name of the tag",}, + "user": {"type": "string", "description": "name of the user that trigger the build",}, + "version": {"type": "string", "description": "version of the build",}, + "owner": {"type": "string", "description": "name of the package owner",}, + "release": {"type": "string", "description": "release number of the package",}, + }, + } + + @property + def build_id(self) -> int: + return self.body["build_id"] + + @property + def name(self) -> str: + return self.body["name"] + + @property + def tag_id(self) -> int: + return self.body["tag_id"] + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def tag(self) -> str: + return self.body["tag"] + + @property + def user(self) -> str: + return self.body["user"] + + @property + def version(self) -> str: + return self.body["version"] + + @property + def owner(self) -> str: + return self.body["owner"] + + @property + def release(self) -> str: + return self.body["release"] diff --git a/koji_fedmsg_plugin/messages/task.py b/koji_fedmsg_plugin/messages/task.py new file mode 100644 index 0000000..86b2401 --- /dev/null +++ b/koji_fedmsg_plugin/messages/task.py @@ -0,0 +1,112 @@ +# Copyright © 2020 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Define schema for fedora messages sent by koji""" + + +from fedora_messaging import message + +SCHEMA_URL = "https://koji-fedmsg-plugin.readthedocs.io/en/latest/_schema" + + +class TaskStateChangeV1(message.Message): + """ This message is sent when a task state changes. """ + + topic = "buildsys.task.state.change" + + body_schema = { + "$id": f"{SCHEMA_URL}/v1/{topic}#", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "description": "A koji task state changed.", + "type": "object", + "properties": { + "info": { + "type": "object", + "description": "task info", + "properties": { + "parent": {"type": ["null", "array"], "description": "parent tasks",}, + "completion_time": {"type": "number", "description": "completion time",}, + "start_time": {"type": "number", "description": "start time",}, + "request": { + "type": ["null", "array"], + "description": "task request details", + "contains": {"type": "string"}, + }, + "waiting": {"type": "boolean", "description": "Is the task waiting or not",}, + "awaited": {"type": "null", "description": "awaited",}, + "id": {"type": "integer", "description": "id",}, + "priority": {"type": "integer", "description": "priority",}, + "channel_id": {"type": "integer", "description": "channel_id",}, + "state": {"type": "integer", "description": "task state",}, + "create_time": {"type": "number", "description": "create time",}, + "result": {"type": "null", "description": "result",}, + "owner": { + "type": ["null", "string", "integer"], + "description": "owner name or id", + }, + "host_id": {"type": "integer", "description": "host id",}, + "method": {"type": "string", "description": "task method",}, + "label": {"type": "null", "description": "label",}, + "arch": {"type": "string", "description": "task specific architecture",}, + "children": {"type": ["null", "array"], "description": "task childrens",}, + }, + }, + "old": {"type": "string", "description": "previous task state",}, + "attribute": {"type": "string", "description": "attribute"}, + "id": {"type": "integer", "description": "task id",}, + "instance": { + "type": "string", + "description": "distinguish between messages from primary and secondary koji", + }, + "owner": {"type": "string", "description": "name of the package owner",}, + "new": {"type": "string", "description": "name of the new task state",}, + "srpm": {"type": "string", "description": "name of the source rpm",}, + "method": {"type": "string", "description": "name of the task method"}, + }, + } + + @property + def info(self) -> dict: + return self.body["info"] + + @property + def old(self) -> str: + return self.body["old"] + + @property + def attribute(self) -> str: + return self.body["attribute"] + + @property + def id(self) -> int: + return self.body["id"] + + @property + def instance(self) -> str: + return self.body["instance"] + + @property + def owner(self) -> str: + return self.body["owner"] + + @property + def new(self) -> str: + return self.body["new"] + + @property + def srpm(self) -> str: + return self.body["srpm"] + + @property + def method(self) -> str: + return self.body["method"] diff --git a/koji_fedmsg_plugin/tests/__init__.py b/koji_fedmsg_plugin/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/koji_fedmsg_plugin/tests/__init__.py diff --git a/koji_fedmsg_plugin/tests/messages/__init__.py b/koji_fedmsg_plugin/tests/messages/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/__init__.py diff --git a/koji_fedmsg_plugin/tests/messages/test_build.py b/koji_fedmsg_plugin/tests/messages/test_build.py new file mode 100644 index 0000000..0da5413 --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_build.py @@ -0,0 +1,33 @@ +from koji_fedmsg_plugin.messages.build import BuildStateChangeV1 + + +def test_build_state_change_message(): + + body = { + "build_id": 1478312, + "old": 0, + "name": "chromium", + "task_id": 42561864, + "attribute": "state", + "request": [ + "git+https://src.fedoraproject.org/rpms/chromium.git#5f8f367e482fe8e30711aea49bf2ecfd163d278f", + "rawhide", + {}, + ], + "instance": "primary", + "epoch": None, + "version": "80.0.3987.132", + "owner": "spot", + "new": 1, + "release": "1.fc33", + } + + msg = BuildStateChangeV1(body=body) + msg.validate() + assert msg.build_id == 1478312 + assert msg.name == "chromium" + assert msg.owner == "spot" + assert msg.version == "80.0.3987.132" + assert msg.release == "1.fc33" + assert msg.old == 0 + assert msg.new == 1 diff --git a/koji_fedmsg_plugin/tests/messages/test_package.py b/koji_fedmsg_plugin/tests/messages/test_package.py new file mode 100644 index 0000000..295945b --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_package.py @@ -0,0 +1,51 @@ +from koji_fedmsg_plugin.messages.package import ListChangeV1 + + +def test_package_list_change_message1(): + + body = { + "force": None, + "instance": "primary", + "extra_arches": None, + "package": "rust-ripgrep", + "update": None, + "owner": None, + "tag": "f31", + "action": "unblock", + "block": None, + } + + msg = ListChangeV1(body=body) + msg.validate() + assert msg.force is None + assert msg.package == "rust-ripgrep" + assert msg.owner is None + assert msg.update is None + assert msg.action == "unblock" + assert msg.tag == "f31" + assert msg.block is None + + +def test_package_list_change_message2(): + + body = { + "force": True, + "instance": "primary", + "extra_arches": "", + "package": "rust-dua-cli", + "update": False, + "owner": "releng", + "tag": "f31-build-side-20267", + "action": "add", + "block": False, + } + + msg = ListChangeV1(body=body) + msg.validate() + assert msg.force + assert msg.package == "rust-dua-cli" + assert msg.owner == "releng" + assert not msg.update + assert msg.action == "add" + assert msg.tag == "f31-build-side-20267" + assert not msg.block diff --git a/koji_fedmsg_plugin/tests/messages/test_repo.py b/koji_fedmsg_plugin/tests/messages/test_repo.py new file mode 100644 index 0000000..7e4d09b --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_repo.py @@ -0,0 +1,27 @@ +from koji_fedmsg_plugin.messages.repo import DoneV1, InitV1 + + +def test_repo_done_message(): + + body = { + "instance": "primary", + "repo_id": 1409150, + "tag": "module-jmc-latest-3220200311144307-089fddd9-build", + "tag_id": 20164, + } + + msg = DoneV1(body=body) + msg.validate() + assert msg.instance == "primary" + assert msg.tag == "module-jmc-latest-3220200311144307-089fddd9-build" + assert msg.tag_id == 20164 + + +def test_repo_init_message(): + + body = {"instance": "primary", "repo_id": 1410901, "tag": "f33-build", "tag_id": 18677} + + msg = InitV1(body=body) + msg.validate() + assert msg.instance == "primary" + assert msg.tag == "f33-build" diff --git a/koji_fedmsg_plugin/tests/messages/test_rpm.py b/koji_fedmsg_plugin/tests/messages/test_rpm.py new file mode 100644 index 0000000..745ae94 --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_rpm.py @@ -0,0 +1,63 @@ +from koji_fedmsg_plugin.messages.rpm import SignV1 + + +def test_rpm_sign_message(): + + body = { + "instance": "primary", + "sigkey": "12c944d0", + "rpm": { + "build_id": 1478177, + "name": "wine-opencl-debuginfo", + "extra": None, + "arch": "aarch64", + "buildtime": 1584471339, + "id": 20905366, + "epoch": None, + "version": "5.4", + "metadata_only": False, + "external_repo_id": 0, + "release": "1.fc32", + "size": 39178, + "buildroot_id": 19890121, + "external_repo_name": "INTERNAL", + "payloadhash": "61affc5b3f9600cd0ade2126779abf62", + }, + "build": { + "cg_id": None, + "package_name": "wine", + "extra": { + "source": { + "original_url": "git+https://src.fedoraproject.org/rpms/wine.git#f83582e8bcf2cbd1eaf693356cfc24731ab85e3f" + } + }, + "creation_time": 1584471219.0, + "completion_time": 1584473659.0, + "package_id": 4106, + "cg_name": None, + "id": 1478177, + "build_id": 1478177, + "epoch": None, + "source": "git+https://src.fedoraproject.org/rpms/wine.git#f83582e8bcf2cbd1eaf693356cfc24731ab85e3f", + "state": 1, + "version": "5.4", + "owner_id": 895, + "owner_name": "mooninite", + "nvr": "wine-5.4-1.fc32", + "start_time": 1584471219.0, + "creation_event_id": 53216169, + "volume_id": 0, + "creation_ts": 1584471219.82997, + "name": "wine", + "task_id": 42567650, + "volume_name": "DEFAULT", + "release": "1.fc32", + }, + "sighash": "a1957f36d34d29c105f16aae79b19e85", + } + + msg = SignV1(body=body) + msg.validate() + assert msg.sigkey == "12c944d0" + assert msg.rpm["name"] == "wine-opencl-debuginfo" + assert msg.build["package_name"] == "wine" diff --git a/koji_fedmsg_plugin/tests/messages/test_tag.py b/koji_fedmsg_plugin/tests/messages/test_tag.py new file mode 100644 index 0000000..471a8fd --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_tag.py @@ -0,0 +1,43 @@ +from koji_fedmsg_plugin.messages.tag import TagV1, UntagV1 + + +def test_tag_message(): + + body = { + "build_id": 1457909, + "name": "http-parser", + "tag_id": 6446, + "instance": "primary", + "tag": "f31-updates-pending", + "user": "bodhi", + "version": "2.9.3", + "owner": "sgallagh", + "release": "1.fc31", + } + + msg = TagV1(body=body) + msg.validate() + assert msg.build_id == 1457909 + assert msg.name == "http-parser" + assert msg.tag == "f31-updates-pending" + + +def test_untag_message(): + + body = { + "build_id": 1478431, + "name": "python-twisted", + "tag_id": 10321, + "instance": "primary", + "tag": "epel8-signing-pending", + "user": "autopen", + "version": "19.10.0", + "owner": "eclipseo", + "release": "2.el8", + } + + msg = UntagV1(body=body) + msg.validate() + assert msg.build_id == 1478431 + assert msg.name == "python-twisted" + assert msg.tag == "epel8-signing-pending" diff --git a/koji_fedmsg_plugin/tests/messages/test_task.py b/koji_fedmsg_plugin/tests/messages/test_task.py new file mode 100644 index 0000000..2d4c2bb --- /dev/null +++ b/koji_fedmsg_plugin/tests/messages/test_task.py @@ -0,0 +1,116 @@ +from koji_fedmsg_plugin.messages.task import TaskStateChangeV1 + + +def test_task_state_change_message(): + + body = { + "info": { + "parent": None, + "completion_time": 1584475720.0, + "start_time": 1584475492.0, + "request": [ + "../packages/libfreehand/0.1.2/6.fc32/src/libfreehand-0.1.2-6.fc32.src.rpm", + "f33", + {"scratch": True, "arch_override": "ppc64le x86_64 aarch64"}, + ], + "waiting": False, + "awaited": None, + "id": 42569071, + "priority": 50, + "channel_id": 1, + "state": 2, + "create_time": 1584475491.0, + "result": None, + "owner": 3199, + "host_id": 303, + "method": "build", + "label": None, + "arch": "noarch", + "children": [ + { + "parent": 42569071, + "completion_time": 1584475672.0, + "start_time": 1584475573.0, + "waiting": None, + "awaited": False, + "label": "ppc64le", + "priority": 49, + "channel_id": 1, + "state": 2, + "create_time": 1584475570.0, + "owner": 3199, + "host_id": 358, + "method": "buildArch", + "arch": "ppc64le", + "id": 42569109, + }, + { + "parent": 42569071, + "completion_time": 1584475719.0, + "start_time": 1584475591.0, + "waiting": None, + "awaited": False, + "label": "aarch64", + "priority": 49, + "channel_id": 1, + "state": 2, + "create_time": 1584475570.0, + "owner": 3199, + "host_id": 222, + "method": "buildArch", + "arch": "aarch64", + "id": 42569111, + }, + { + "parent": 42569071, + "completion_time": 1584475658.0, + "start_time": 1584475571.0, + "waiting": None, + "awaited": False, + "label": "x86_64", + "priority": 49, + "channel_id": 1, + "state": 2, + "create_time": 1584475570.0, + "owner": 3199, + "host_id": 71, + "method": "buildArch", + "arch": "x86_64", + "id": 42569110, + }, + { + "parent": 42569071, + "completion_time": 1584475554.0, + "start_time": 1584475493.0, + "waiting": None, + "awaited": False, + "label": "srpm", + "priority": 49, + "channel_id": 1, + "state": 2, + "create_time": 1584475492.0, + "owner": 3199, + "host_id": 204, + "method": "rebuildSRPM", + "arch": "noarch", + "id": 42569074, + }, + ], + }, + "old": "OPEN", + "attribute": "state", + "id": 42569071, + "instance": "primary", + "owner": "koschei", + "new": "CLOSED", + "srpm": "libfreehand-0.1.2-6.fc32.src.rpm", + "method": "build", + } + + msg = TaskStateChangeV1(body=body) + msg.validate() + assert msg.old == "OPEN" + assert msg.new == "CLOSED" + assert msg.method == "build" + assert msg.info["create_time"] == 1584475491.0 + assert msg.info["children"][0]["arch"] == "ppc64le" diff --git a/poetry.lock b/poetry.lock index 46f1d21..a15ece9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,29 @@ [[package]] +category = "dev" +description = "A configurable sidebar-enabled Sphinx theme" +name = "alabaster" +optional = false +python-versions = "*" +version = "0.7.12" + +[[package]] +category = "dev" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" +optional = false +python-versions = "*" +version = "1.4.3" + +[[package]] +category = "dev" +description = "Atomic file writes." +marker = "sys_platform == \"win32\"" +name = "atomicwrites" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.3.0" + +[[package]] category = "main" description = "Classes Without Boilerplate" name = "attrs" @@ -28,6 +53,37 @@ six = "*" visualize = ["graphviz (>0.5.1)", "Twisted (>=16.1.1)"] [[package]] +category = "dev" +description = "Internationalization utilities" +name = "babel" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.8.0" + +[package.dependencies] +pytz = ">=2015.7" + +[[package]] +category = "dev" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6" +version = "19.10b0" + +[package.dependencies] +appdirs = "*" +attrs = ">=18.1.0" +click = ">=6.5" +pathspec = ">=0.6,<1" +regex = "*" +toml = ">=0.9.4" +typed-ast = ">=1.4.0" + +[package.extras] +d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] + +[[package]] category = "main" description = "Fast, simple object-to-object and broadcast signaling" name = "blinker" @@ -36,6 +92,14 @@ python-versions = "*" version = "1.4" [[package]] +category = "dev" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2019.11.28" + +[[package]] category = "main" description = "Foreign Function Interface for Python calling C code." name = "cffi" @@ -47,25 +111,29 @@ version = "1.14.0" pycparser = "*" [[package]] +category = "dev" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] category = "main" description = "Composable command line interface toolkit" name = "click" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.1" [[package]] -category = "main" -description = "Updated configparser from Python 3.7 for Python 2.6+." -marker = "python_version < \"3\"" -name = "configparser" +category = "dev" +description = "Cross-platform colored terminal text." +marker = "sys_platform == \"win32\"" +name = "colorama" optional = false -python-versions = ">=2.6" -version = "4.0.2" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytest-flake8", "pytest-black-multipy"] +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.3" [[package]] category = "main" @@ -77,15 +145,6 @@ version = "15.1.0" [[package]] category = "main" -description = "Backports and enhancements for the contextlib module" -marker = "python_version < \"3.4\"" -name = "contextlib2" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.6.0.post1" - -[[package]] -category = "main" description = "Use Twisted anywhere!" name = "crochet" optional = false @@ -108,14 +167,6 @@ version = "2.8" cffi = ">=1.8,<1.11.3 || >1.11.3" six = ">=1.4.1" -[package.dependencies.enum34] -python = "<3" -version = "*" - -[package.dependencies.ipaddress] -python = "<3" -version = "*" - [package.extras] docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"] docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] @@ -124,13 +175,20 @@ pep8test = ["flake8", "flake8-import-order", "pep8-naming"] test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] [[package]] -category = "main" -description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4" -marker = "python_version < \"3\"" -name = "enum34" +category = "dev" +description = "Docutils -- Python Documentation Utilities" +name = "docutils" optional = false -python-versions = "*" -version = "1.1.10" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.16" + +[[package]] +category = "dev" +description = "Discover and load entry points from installed packages." +name = "entrypoints" +optional = false +python-versions = ">=2.7" +version = "0.3" [[package]] category = "main" @@ -154,13 +212,18 @@ six = "*" toml = "*" [[package]] -category = "main" -description = "Backport of the functools module from Python 3.2.3 for use on 2.7 and PyPy." -marker = "python_version < \"3\"" -name = "functools32" +category = "dev" +description = "the modular source code checker: pep8, pyflakes and co" +name = "flake8" optional = false -python-versions = "*" -version = "3.2.3-2" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.7.9" + +[package.dependencies] +entrypoints = ">=0.3.0,<0.4.0" +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.5.0,<2.6.0" +pyflakes = ">=2.1.0,<2.2.0" [[package]] category = "main" @@ -182,25 +245,25 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.9" [[package]] +category = "dev" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +name = "imagesize" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.0" + +[[package]] category = "main" description = "Read metadata from Python packages" marker = "python_version < \"3.8\"" name = "importlib-metadata" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.1.3" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.5.0" [package.dependencies] zipp = ">=0.5" -[package.dependencies.configparser] -python = "<3" -version = ">=3.5" - -[package.dependencies.contextlib2] -python = "<3" -version = "*" - [package.extras] docs = ["sphinx", "rst.linker"] testing = ["packaging", "importlib-resources"] @@ -217,13 +280,18 @@ version = "17.5.0" scripts = ["click (>=6.0)", "twisted (>=16.4.0)"] [[package]] -category = "main" -description = "IPv4/IPv6 manipulation library" -marker = "python_version < \"3.3\"" -name = "ipaddress" +category = "dev" +description = "A very fast and expressive template engine." +name = "jinja2" optional = false -python-versions = "*" -version = "1.0.23" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.11.1" + +[package.dependencies] +MarkupSafe = ">=0.23" + +[package.extras] +i18n = ["Babel (>=0.8)"] [[package]] category = "main" @@ -239,10 +307,6 @@ pyrsistent = ">=0.14.0" setuptools = "*" six = ">=1.11.0" -[package.dependencies.functools32] -python = "<3" -version = "*" - [package.dependencies.importlib-metadata] python = "<3.8" version = "*" @@ -252,22 +316,50 @@ format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] [[package]] -category = "main" -description = "Koji is a system for building and tracking RPMS. The base package contains shared libraries and the command-line interface." -name = "koji" +category = "dev" +description = "Safely add untrusted strings to HTML/XML markup." +name = "markupsafe" optional = false -python-versions = ">=2.6" -version = "1.20.1" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.1.1" + +[[package]] +category = "dev" +description = "McCabe checker, plugin for flake8" +name = "mccabe" +optional = false +python-versions = "*" +version = "0.6.1" + +[[package]] +category = "dev" +description = "More routines for operating on iterables, beyond itertools" +name = "more-itertools" +optional = false +python-versions = ">=3.5" +version = "8.2.0" + +[[package]] +category = "dev" +description = "Core utilities for Python packages" +name = "packaging" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.3" [package.dependencies] -pyOpenSSL = "*" -python-dateutil = "*" -python-krbV = "*" -requests = "*" -requests-kerberos = "*" +pyparsing = ">=2.0.2" six = "*" [[package]] +category = "dev" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.7.0" + +[[package]] category = "main" description = "Pika Python AMQP Client Library" name = "pika" @@ -280,6 +372,30 @@ tornado = ["tornado"] twisted = ["twisted"] [[package]] +category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" + +[package.dependencies] +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +dev = ["pre-commit", "tox"] + +[[package]] +category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.8.1" + +[[package]] category = "main" description = "ASN.1 types and codecs" name = "pyasn1" @@ -299,6 +415,14 @@ version = "0.2.8" pyasn1 = ">=0.4.6,<0.5.0" [[package]] +category = "dev" +description = "Python style guide checker" +name = "pycodestyle" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.5.0" + +[[package]] category = "main" description = "C parser in Python" name = "pycparser" @@ -307,25 +431,28 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.20" [[package]] -category = "main" -description = "Hamcrest framework for matcher objects" -name = "pyhamcrest" +category = "dev" +description = "passive checker of Python programs" +name = "pyflakes" optional = false -python-versions = "*" -version = "1.9.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.1.1" -[package.dependencies] -setuptools = "*" -six = "*" +[[package]] +category = "dev" +description = "Pygments is a syntax highlighting package written in Python." +name = "pygments" +optional = false +python-versions = ">=3.5" +version = "2.6.1" [[package]] category = "main" -description = "High-level interface to Kerberos" -marker = "sys_platform != \"win32\"" -name = "pykerberos" +description = "Hamcrest framework for matcher objects" +name = "pyhamcrest" optional = false -python-versions = "*" -version = "1.2.1" +python-versions = ">=3.5" +version = "2.0.2" [[package]] category = "main" @@ -344,6 +471,14 @@ docs = ["sphinx", "sphinx-rtd-theme"] test = ["flaky", "pretend", "pytest (>=3.0.1)"] [[package]] +category = "dev" +description = "Python parsing module" +name = "pyparsing" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.6" + +[[package]] category = "main" description = "Persistent/Functional/Immutable data structures" name = "pyrsistent" @@ -355,23 +490,30 @@ version = "0.15.7" six = "*" [[package]] -category = "main" -description = "Extensions to the standard Python datetime module" -name = "python-dateutil" +category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" +python-versions = ">=3.5" +version = "5.4.1" [package.dependencies] -six = ">=1.5" +atomicwrites = ">=1.0" +attrs = ">=17.4.0" +colorama = "*" +more-itertools = ">=4.0.0" +packaging = "*" +pluggy = ">=0.12,<1.0" +py = ">=1.5.0" +wcwidth = "*" -[[package]] -category = "main" -description = "Python extension module for Kerberos 5" -name = "python-krbv" -optional = false -python-versions = "*" -version = "1.0.90" +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +checkqa-mypy = ["mypy (v0.761)"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] category = "main" @@ -382,33 +524,30 @@ python-versions = "*" version = "2019.3" [[package]] -category = "main" -description = "Python HTTP for Humans." -name = "requests" +category = "dev" +description = "Alternative regular expression module, to replace re." +name = "regex" optional = false python-versions = "*" -version = "2.15.1" - -[package.extras] -security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +version = "2020.2.20" [[package]] -category = "main" -description = "A Kerberos authentication handler for python-requests" -name = "requests-kerberos" +category = "dev" +description = "Python HTTP for Humans." +name = "requests" optional = false -python-versions = "*" -version = "0.12.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.23.0" [package.dependencies] -pykerberos = ">=1.1.8,<2.0.0" -requests = ">=1.1.0" -winkerberos = ">=0.5.0" +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" -[package.dependencies.cryptography] -python = "<3.3.0 || >=3.4.0" -version = ">=1.3" +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] category = "main" @@ -424,10 +563,6 @@ cryptography = "*" pyasn1 = "*" pyasn1-modules = "*" -[package.dependencies.ipaddress] -python = "<3.3" -version = "*" - [package.extras] dev = ["coverage (>=4.2.0)", "pytest", "sphinx", "idna", "pyopenssl"] docs = ["sphinx"] @@ -443,6 +578,116 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" version = "1.14.0" [[package]] +category = "dev" +description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +name = "snowballstemmer" +optional = false +python-versions = "*" +version = "2.0.0" + +[[package]] +category = "dev" +description = "Python documentation generator" +name = "sphinx" +optional = false +python-versions = ">=3.5" +version = "2.4.4" + +[package.dependencies] +Jinja2 = ">=2.3" +Pygments = ">=2.0" +alabaster = ">=0.7,<0.8" +babel = ">=1.3,<2.0 || >2.0" +colorama = ">=0.3.5" +docutils = ">=0.12" +imagesize = "*" +packaging = "*" +requests = ">=2.5.0" +setuptools = "*" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = "*" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = "*" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +test = ["pytest (<5.3.3)", "pytest-cov", "html5lib", "flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.761)", "docutils-stubs"] + +[[package]] +category = "dev" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +name = "sphinxcontrib-applehelp" +optional = false +python-versions = ">=3.5" +version = "1.0.2" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +name = "sphinxcontrib-devhelp" +optional = false +python-versions = ">=3.5" +version = "1.0.2" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +name = "sphinxcontrib-htmlhelp" +optional = false +python-versions = ">=3.5" +version = "1.0.3" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest", "html5lib"] + +[[package]] +category = "dev" +description = "A sphinx extension which renders display math in HTML via JavaScript" +name = "sphinxcontrib-jsmath" +optional = false +python-versions = ">=3.5" +version = "1.0.1" + +[package.extras] +test = ["pytest", "flake8", "mypy"] + +[[package]] +category = "dev" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +name = "sphinxcontrib-qthelp" +optional = false +python-versions = ">=3.5" +version = "1.0.3" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +name = "sphinxcontrib-serializinghtml" +optional = false +python-versions = ">=3.5" +version = "1.1.4" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] category = "main" description = "Python Library for Tom's Obvious, Minimal Language" name = "toml" @@ -480,13 +725,33 @@ tls = ["pyopenssl (>=16.0.0)", "service_identity (>=18.1.0)", "idna (>=0.6,<2.3 windows_platform = ["pywin32", "pyopenssl (>=16.0.0)", "service_identity (>=18.1.0)", "idna (>=0.6,<2.3 || >2.3)", "pyasn1", "cryptography (>=2.5)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "soappy", "pyserial (>=3.0)", "h2 (>=3.0,<4.0)", "priority (>=1.1.0,<2.0)", "pywin32"] [[package]] -category = "main" -description = "High level interface to SSPI for Kerberos client auth" -marker = "sys_platform == \"win32\"" -name = "winkerberos" +category = "dev" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" optional = false python-versions = "*" -version = "0.7.0" +version = "1.4.1" + +[[package]] +category = "dev" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.8" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[[package]] +category = "dev" +description = "Measures number of Terminal column cells of wide-character codes" +name = "wcwidth" +optional = false +python-versions = "*" +version = "0.1.8" [[package]] category = "main" @@ -505,11 +770,6 @@ optional = false python-versions = ">=2.7" version = "1.2.0" -[package.dependencies] -[package.dependencies.contextlib2] -python = "<3.4" -version = "*" - [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] @@ -519,8 +779,8 @@ category = "main" description = "Interfaces for Python" name = "zope.interface" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.6.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "4.7.2" [package.dependencies] setuptools = "*" @@ -531,10 +791,22 @@ test = ["zope.event"] testing = ["zope.event", "nose", "coverage"] [metadata] -content-hash = "73e2f600a1be90f7d8963d982ca2514d303b35cb6137620de2e4bc60f514bcdb" -python-versions = "*" +content-hash = "97904c5d15a17b72e1cb679263416775c27c29e691dea419d459a4ed8f596567" +python-versions = "^3.6" [metadata.files] +alabaster = [ + {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, + {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, +] +appdirs = [ + {file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"}, + {file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"}, +] +atomicwrites = [ + {file = "atomicwrites-1.3.0-py2.py3-none-any.whl", hash = "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4"}, + {file = "atomicwrites-1.3.0.tar.gz", hash = "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"}, +] attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, @@ -543,9 +815,21 @@ automat = [ {file = "Automat-20.2.0-py2.py3-none-any.whl", hash = "sha256:b6feb6455337df834f6c9962d6ccf771515b7d939bca142b29c20c2376bc6111"}, {file = "Automat-20.2.0.tar.gz", hash = "sha256:7979803c74610e11ef0c0d68a2942b152df52da55336e0c9d58daf1831cbdf33"}, ] +babel = [ + {file = "Babel-2.8.0-py2.py3-none-any.whl", hash = "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"}, + {file = "Babel-2.8.0.tar.gz", hash = "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38"}, +] +black = [ + {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, + {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, +] blinker = [ {file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"}, ] +certifi = [ + {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, + {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, +] cffi = [ {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, {file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, @@ -576,22 +860,22 @@ cffi = [ {file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, {file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, ] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] click = [ - {file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"}, - {file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"}, + {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, + {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, ] -configparser = [ - {file = "configparser-4.0.2-py2.py3-none-any.whl", hash = "sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c"}, - {file = "configparser-4.0.2.tar.gz", hash = "sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df"}, +colorama = [ + {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, + {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, ] constantly = [ {file = "constantly-15.1.0-py2.py3-none-any.whl", hash = "sha256:dd2fa9d6b1a51a83f0d7dd76293d734046aa176e384bf6e33b7e44880eb37c5d"}, {file = "constantly-15.1.0.tar.gz", hash = "sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"}, ] -contextlib2 = [ - {file = "contextlib2-0.6.0.post1-py2.py3-none-any.whl", hash = "sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"}, - {file = "contextlib2-0.6.0.post1.tar.gz", hash = "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e"}, -] crochet = [ {file = "crochet-1.12.0-py3-none-any.whl", hash = "sha256:9b54000f69c499083f3c39ee3e550122419e58e7090e6a3f5afa88604ede86e7"}, {file = "crochet-1.12.0.tar.gz", hash = "sha256:8fcbc64768813f50ee76b17a1e8d32a9f39206f8ab6766d50c885e07e7fb6fb1"}, @@ -619,18 +903,21 @@ cryptography = [ {file = "cryptography-2.8-cp38-cp38-win_amd64.whl", hash = "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13"}, {file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"}, ] -enum34 = [ - {file = "enum34-1.1.10-py2-none-any.whl", hash = "sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53"}, - {file = "enum34-1.1.10-py3-none-any.whl", hash = "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328"}, - {file = "enum34-1.1.10.tar.gz", hash = "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"}, +docutils = [ + {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, + {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, +] +entrypoints = [ + {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, + {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] fedora-messaging = [ {file = "fedora_messaging-2.0.1-py2.py3-none-any.whl", hash = "sha256:c7faa69b98dbeaa18b89ee892064e48a6b34545bfb2e1973ede6ff2ae4daec46"}, {file = "fedora_messaging-2.0.1.tar.gz", hash = "sha256:72edbe2aece0d358ff4dade9c0cdb76b407cb4f588403ffd33b9c8fd60f619c6"}, ] -functools32 = [ - {file = "functools32-3.2.3-2.tar.gz", hash = "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"}, - {file = "functools32-3.2.3-2.zip", hash = "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0"}, +flake8 = [ + {file = "flake8-3.7.9-py2.py3-none-any.whl", hash = "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"}, + {file = "flake8-3.7.9.tar.gz", hash = "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb"}, ] hyperlink = [ {file = "hyperlink-19.0.0-py2.py3-none-any.whl", hash = "sha256:ab4a308feb039b04f855a020a6eda3b18ca5a68e6d8f8c899cbe9e653721d04f"}, @@ -640,31 +927,89 @@ idna = [ {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] +imagesize = [ + {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, + {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, +] importlib-metadata = [ - {file = "importlib_metadata-1.1.3-py2.py3-none-any.whl", hash = "sha256:7c7f8ac40673f507f349bef2eed21a0e5f01ddf5b2a7356a6c65eb2099b53764"}, - {file = "importlib_metadata-1.1.3.tar.gz", hash = "sha256:7a99fb4084ffe6dae374961ba7a6521b79c1d07c658ab3a28aa264ee1d1b14e3"}, + {file = "importlib_metadata-1.5.0-py2.py3-none-any.whl", hash = "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"}, + {file = "importlib_metadata-1.5.0.tar.gz", hash = "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302"}, ] incremental = [ {file = "incremental-17.5.0-py2.py3-none-any.whl", hash = "sha256:717e12246dddf231a349175f48d74d93e2897244939173b01974ab6661406b9f"}, {file = "incremental-17.5.0.tar.gz", hash = "sha256:7b751696aaf36eebfab537e458929e194460051ccad279c72b755a167eebd4b3"}, ] -ipaddress = [ - {file = "ipaddress-1.0.23-py2.py3-none-any.whl", hash = "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc"}, - {file = "ipaddress-1.0.23.tar.gz", hash = "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2"}, +jinja2 = [ + {file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"}, + {file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"}, ] jsonschema = [ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, ] -koji = [ - {file = "koji-1.20.1-py2-none-any.whl", hash = "sha256:aeb9de853404b95e3c5559d50fbe576cde45a20bf04428df5ec449c25d79e05c"}, - {file = "koji-1.20.1-py3-none-any.whl", hash = "sha256:1313eef22e3ed277d28dc268c69a4bd934f4d7df934b3bd33e867830e1c3f182"}, - {file = "koji-1.20.1.tar.gz", hash = "sha256:c734467aa9b87a8225b1cc7cde468f6864945ee6d439384dab3f63e725008f3f"}, +markupsafe = [ + {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, + {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, + {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, + {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +more-itertools = [ + {file = "more-itertools-8.2.0.tar.gz", hash = "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"}, + {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, +] +packaging = [ + {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, + {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, +] +pathspec = [ + {file = "pathspec-0.7.0-py2.py3-none-any.whl", hash = "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424"}, + {file = "pathspec-0.7.0.tar.gz", hash = "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"}, ] pika = [ {file = "pika-1.1.0-py2.py3-none-any.whl", hash = "sha256:4e1a1a6585a41b2341992ec32aadb7a919d649eb82904fd8e4a4e0871c8cf3af"}, {file = "pika-1.1.0.tar.gz", hash = "sha256:9fa76ba4b65034b878b2b8de90ff8660a59d925b087c5bb88f8fdbb4b64a1dbf"}, ] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] +py = [ + {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, + {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, +] pyasn1 = [ {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, @@ -695,45 +1040,71 @@ pyasn1-modules = [ {file = "pyasn1_modules-0.2.8-py3.6.egg", hash = "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0"}, {file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"}, ] +pycodestyle = [ + {file = "pycodestyle-2.5.0-py2.py3-none-any.whl", hash = "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56"}, + {file = "pycodestyle-2.5.0.tar.gz", hash = "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"}, +] pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] -pyhamcrest = [ - {file = "PyHamcrest-1.9.0-py2.6.egg", hash = "sha256:f30e9a310bcc1808de817a92e95169ffd16b60cbc5a016a49c8d0e8ababfae79"}, - {file = "PyHamcrest-1.9.0-py2.py3-none-any.whl", hash = "sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420"}, - {file = "PyHamcrest-1.9.0-py3.2.egg", hash = "sha256:bac0bea7358666ce52e3c6c85139632ed89f115e9af52d44b3c36e0bf8cf16a9"}, - {file = "PyHamcrest-1.9.0-py3.4.egg", hash = "sha256:7a4bdade0ed98c699d728191a058a60a44d2f9c213c51e2dd1e6fb42f2c6128a"}, - {file = "PyHamcrest-1.9.0.tar.gz", hash = "sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"}, +pyflakes = [ + {file = "pyflakes-2.1.1-py2.py3-none-any.whl", hash = "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0"}, + {file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"}, +] +pygments = [ + {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, + {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, ] -pykerberos = [ - {file = "pykerberos-1.2.1.tar.gz", hash = "sha256:4f2dca8df5f84a3be039c026893850d731a8bb38395292e1610ffb0a08ba876c"}, +pyhamcrest = [ + {file = "PyHamcrest-2.0.2-py3-none-any.whl", hash = "sha256:7ead136e03655af85069b6f47b23eb7c3e5c221aa9f022a4fbb499f5b7308f29"}, + {file = "PyHamcrest-2.0.2.tar.gz", hash = "sha256:412e00137858f04bde0729913874a48485665f2d36fe9ee449f26be864af9316"}, ] pyopenssl = [ {file = "pyOpenSSL-19.1.0-py2.py3-none-any.whl", hash = "sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504"}, {file = "pyOpenSSL-19.1.0.tar.gz", hash = "sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507"}, ] +pyparsing = [ + {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, + {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, +] pyrsistent = [ {file = "pyrsistent-0.15.7.tar.gz", hash = "sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"}, ] -python-dateutil = [ - {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, - {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, -] -python-krbv = [ - {file = "python-krbV-1.0.90.tar.bz2", hash = "sha256:b2e1544e3f600a8f5f403ca9038d8079e31271cb7560904d5453a2be8784ed7e"}, +pytest = [ + {file = "pytest-5.4.1-py3-none-any.whl", hash = "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172"}, + {file = "pytest-5.4.1.tar.gz", hash = "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, ] -requests = [ - {file = "requests-2.15.1-py2.py3-none-any.whl", hash = "sha256:ff753b2196cd18b1bbeddc9dcd5c864056599f7a7d9a4fb5677e723efa2b7fb9"}, - {file = "requests-2.15.1.tar.gz", hash = "sha256:e5659b9315a0610505e050bb7190bf6fa2ccee1ac295f2b760ef9d8a03ebbb2e"}, +regex = [ + {file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"}, + {file = "regex-2020.2.20-cp27-cp27m-win_amd64.whl", hash = "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"}, + {file = "regex-2020.2.20-cp36-cp36m-win32.whl", hash = "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69"}, + {file = "regex-2020.2.20-cp36-cp36m-win_amd64.whl", hash = "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab"}, + {file = "regex-2020.2.20-cp37-cp37m-win32.whl", hash = "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431"}, + {file = "regex-2020.2.20-cp37-cp37m-win_amd64.whl", hash = "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux1_i686.whl", hash = "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70"}, + {file = "regex-2020.2.20-cp38-cp38-win32.whl", hash = "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d"}, + {file = "regex-2020.2.20-cp38-cp38-win_amd64.whl", hash = "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa"}, + {file = "regex-2020.2.20.tar.gz", hash = "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5"}, ] -requests-kerberos = [ - {file = "requests-kerberos-0.12.0.tar.gz", hash = "sha256:9d21f15241c53c2ad47e813138b9aee4b9acdd04b82048c4388ade15f40a52fd"}, - {file = "requests_kerberos-0.12.0-py2.py3-none-any.whl", hash = "sha256:5733abc0b6524815f6fc72d5c0ec9f3fb89137b852adea2a461c45931f5675e0"}, +requests = [ + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, ] service-identity = [ {file = "service_identity-18.1.0-py2.py3-none-any.whl", hash = "sha256:001c0707759cb3de7e49c078a7c0c9cd12594161d3bf06b9c254fdcb1a60dc36"}, @@ -743,6 +1114,38 @@ six = [ {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] +snowballstemmer = [ + {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, + {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, +] +sphinx = [ + {file = "Sphinx-2.4.4-py3-none-any.whl", hash = "sha256:fc312670b56cb54920d6cc2ced455a22a547910de10b3142276495ced49231cb"}, + {file = "Sphinx-2.4.4.tar.gz", hash = "sha256:b4c750d546ab6d7e05bdff6ac24db8ae3e8b8253a3569b754e445110a0a12b66"}, +] +sphinxcontrib-applehelp = [ + {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"}, +] +sphinxcontrib-devhelp = [ + {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"}, +] +sphinxcontrib-htmlhelp = [ + {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, + {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, +] +sphinxcontrib-jsmath = [ + {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"}, +] +sphinxcontrib-qthelp = [ + {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"}, +] +sphinxcontrib-serializinghtml = [ + {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, + {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, +] toml = [ {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, @@ -769,22 +1172,36 @@ twisted = [ {file = "Twisted-19.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f1fe9139fdcf7721d308e36c51cf975474678a8241a9799af02a7bb1c531b722"}, {file = "Twisted-19.10.0.tar.bz2", hash = "sha256:7394ba7f272ae722a74f3d969dcf599bc4ef093bc392038748a490f1724a515d"}, ] -winkerberos = [ - {file = "winkerberos-0.7.0-cp26-cp26m-win32.whl", hash = "sha256:541d9ba58d310a8f06f045e6e2d55d25462b26e1425cc997b6813c4e91c33b4c"}, - {file = "winkerberos-0.7.0-cp26-cp26m-win_amd64.whl", hash = "sha256:c078ebfcfe65ce68cf59d00293ad5dd3e11b6d7fba4ee0f2cd333fa33ccea3c5"}, - {file = "winkerberos-0.7.0-cp27-cp27m-win32.whl", hash = "sha256:3e6ad24331b6bd020e43e60357463a1a73d47c935b918255796fc617ba6fae8f"}, - {file = "winkerberos-0.7.0-cp27-cp27m-win_amd64.whl", hash = "sha256:95af58f2d24a93598ef6d11341910621fd4170912c82b5e5d793f2cafa0daf1f"}, - {file = "winkerberos-0.7.0-cp33-cp33m-win32.whl", hash = "sha256:47b0279b734b2f497ae20172a3d0ee6dc81be642df5a51fc0a88b695123f4061"}, - {file = "winkerberos-0.7.0-cp33-cp33m-win_amd64.whl", hash = "sha256:764728ce71f7150da664a9dd4398ecfdd1e44fdb50c5d9fdce719f93b8897de0"}, - {file = "winkerberos-0.7.0-cp34-cp34m-win32.whl", hash = "sha256:d695f7990f8c04fec11dc64093d6107e42b67263a73653b6ad052d95403d6409"}, - {file = "winkerberos-0.7.0-cp34-cp34m-win_amd64.whl", hash = "sha256:494358695b1d05342af04149b531ed45bcfd9b351b05f67fc3a0dbb7b5ac3851"}, - {file = "winkerberos-0.7.0-cp35-cp35m-win32.whl", hash = "sha256:76d22b53fb7d6a9a46e4adce644f7be0023e4e05bcc1e9c27569d1bfe12df8bc"}, - {file = "winkerberos-0.7.0-cp35-cp35m-win_amd64.whl", hash = "sha256:7c1bb92e0692ebd5b91bb2e11122f72c8da367c9524c0a25326cfd62833195a5"}, - {file = "winkerberos-0.7.0-cp36-cp36m-win32.whl", hash = "sha256:712f29aec8a6d1bb87e8a05e9a65db3cfc6aa041334e2e3c0d5baebf9433471f"}, - {file = "winkerberos-0.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:240a1678c320501ade115511b4d10d44b9ff8e7d724b053dc5b3544cbfe6753b"}, - {file = "winkerberos-0.7.0-cp37-cp37m-win32.whl", hash = "sha256:14dbbcaeacc13aee0fc8a1d0bb12a29500642fe616c41b50bd9e0ff962372ec9"}, - {file = "winkerberos-0.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0ca44087ab43979b0d8ffccb25353c8955d0bf755718405bcd2ad5e889eddfa8"}, - {file = "winkerberos-0.7.0.zip", hash = "sha256:e304c28de838a48206edfe58b8deb5209a3fd8c6a755bd521c1ee6e656b06e27"}, +typed-ast = [ + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, + {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, + {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, + {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, + {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, +] +urllib3 = [ + {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, + {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, +] +wcwidth = [ + {file = "wcwidth-0.1.8-py2.py3-none-any.whl", hash = "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"}, + {file = "wcwidth-0.1.8.tar.gz", hash = "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"}, ] wrapt = [ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, @@ -794,33 +1211,43 @@ zipp = [ {file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"}, ] "zope.interface" = [ - {file = "zope.interface-4.6.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:a15e75d284178afe529a536b0e8b28b7e107ef39626a7809b4ee64ff3abc9127"}, - {file = "zope.interface-4.6.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:bbcef00d09a30948756c5968863316c949d9cedbc7aabac5e8f0ffbdb632e5f1"}, - {file = "zope.interface-4.6.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9e998ba87df77a85c7bed53240a7257afe51a07ee6bc3445a0bf841886da0b97"}, - {file = "zope.interface-4.6.0-cp27-cp27m-win32.whl", hash = "sha256:20a12ab46a7e72b89ce0671e7d7a6c3c1ca2c2766ac98112f78c5bddaa6e4375"}, - {file = "zope.interface-4.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:d788a3999014ddf416f2dc454efa4a5dbeda657c6aba031cf363741273804c6b"}, - {file = "zope.interface-4.6.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7e5c9a5012b2b33e87980cee7d1c82412b2ebabcb5862d53413ba1a2cfde23aa"}, - {file = "zope.interface-4.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bad44274b151d46619a7567010f7cde23a908c6faa84b97598fd2f474a0c6891"}, - {file = "zope.interface-4.6.0-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:7040547e5b882349c0a2cc9b50674b1745db551f330746af434aad4f09fba2cc"}, - {file = "zope.interface-4.6.0-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:81295629128f929e73be4ccfdd943a0906e5fe3cdb0d43ff1e5144d16fbb52b1"}, - {file = "zope.interface-4.6.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:298f82c0ab1b182bd1f34f347ea97dde0fffb9ecf850ecf7f8904b8442a07487"}, - {file = "zope.interface-4.6.0-cp34-cp34m-win32.whl", hash = "sha256:7e099fde2cce8b29434684f82977db4e24f0efa8b0508179fce1602d103296a2"}, - {file = "zope.interface-4.6.0-cp34-cp34m-win_amd64.whl", hash = "sha256:f99451f3a579e73b5dd58b1b08d1179791d49084371d9a47baad3b22417f0317"}, - {file = "zope.interface-4.6.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:3b877de633a0f6d81b600624ff9137312d8b1d0f517064dfc39999352ab659f0"}, - {file = "zope.interface-4.6.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b639f72b95389620c1f881d94739c614d385406ab1d6926a9ffe1c8abbea23fe"}, - {file = "zope.interface-4.6.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:11ebddf765bff3bbe8dbce10c86884d87f90ed66ee410a7e6c392086e2c63d02"}, - {file = "zope.interface-4.6.0-cp35-cp35m-win32.whl", hash = "sha256:1157b1ec2a1f5bf45668421e3955c60c610e31913cc695b407a574efdbae1f7b"}, - {file = "zope.interface-4.6.0-cp35-cp35m-win_amd64.whl", hash = "sha256:a6a6ff82f5f9b9702478035d8f6fb6903885653bff7ec3a1e011edc9b1a7168d"}, - {file = "zope.interface-4.6.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:4265681e77f5ac5bac0905812b828c9fe1ce80c6f3e3f8574acfb5643aeabc5b"}, - {file = "zope.interface-4.6.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:086707e0f413ff8800d9c4bc26e174f7ee4c9c8b0302fbad68d083071822316c"}, - {file = "zope.interface-4.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5f4d42baed3a14c290a078e2696c5f565501abde1b2f3f1a1c0a94fbf6fbcc39"}, - {file = "zope.interface-4.6.0-cp36-cp36m-win32.whl", hash = "sha256:a0c39e2535a7e9c195af956610dba5a1073071d2d85e9d2e5d789463f63e52ab"}, - {file = "zope.interface-4.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968d5c5702da15c5bf8e4a6e4b67a4d92164e334e9c0b6acf080106678230b98"}, - {file = "zope.interface-4.6.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:14b242d53f6f35c2d07aa2c0e13ccb710392bcd203e1b82a1828d216f6f6b11f"}, - {file = "zope.interface-4.6.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:2f6175722da6f23dbfc76c26c241b67b020e1e83ec7fe93c9e5d3dd18667ada2"}, - {file = "zope.interface-4.6.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eed88ae03e1ef3a75a0e96a55a99d7937ed03e53d0cffc2451c208db445a2966"}, - {file = "zope.interface-4.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:95cc574b0b83b85be9917d37cd2fad0ce5a0d21b024e1a5804d044aabea636fc"}, - {file = "zope.interface-4.6.0-cp37-cp37m-win32.whl", hash = "sha256:62dd71dbed8cc6a18379700701d959307823b3b2451bdc018594c48956ace745"}, - {file = "zope.interface-4.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:550695c4e7313555549aa1cdb978dc9413d61307531f123558e438871a883d63"}, - {file = "zope.interface-4.6.0.tar.gz", hash = "sha256:1b3d0dcabc7c90b470e59e38a9acaa361be43b3a6ea644c0063951964717f0e5"}, + {file = "zope.interface-4.7.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:34381fcecc6e6f57d72bc2fab6175976eeacdd61dbb34427a37b260238278199"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4d0830e1d544b2c303064ec01923de2b9d6f5b5d0d78608a91d758b0f469361c"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:73a618e734803ded8b8d8f14f9a6371c6a1acc445840cf6ae57733041e796671"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a82d36ecc28e72904388f72f57f3c04aee7c43a019e302d61944b3886c261be3"}, + {file = "zope.interface-4.7.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b0029f193d91a1e0085e4a99dd71e4c63a3e7826ec4a8d2ea457f02e1b6b0bb4"}, + {file = "zope.interface-4.7.2-cp27-cp27m-win32.whl", hash = "sha256:d8a0cb84de725ccd6abd9b5bd32cb94a11db336076fb6d459f1fed23d0719e0c"}, + {file = "zope.interface-4.7.2-cp27-cp27m-win_amd64.whl", hash = "sha256:a36e7e1972109504dfa0995a89b6c24a990113eb4cedef93d0eaf1452901b6ac"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2690fd5b042062d866017db11ce1e12d4862df28614cc2915dc57e52b46a8594"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0616040d5a18786aff5d25ef6e1fa0f875b7ba5b6f1a923c1153be81dd9c65ad"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6f1e8914eee2e3a0bcf435d963ca5cf3a3df89a47cbd3e2b16343bc875194fed"}, + {file = "zope.interface-4.7.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:a41a34c55887743ee124e8f696217dec1a7eead1164d27ef27dfae528c396a23"}, + {file = "zope.interface-4.7.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:1033e7bb858c398580ca7cbb50f15b715e6031d5772f8a1bde4042c12300a52a"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:ae6c4a1fa696c12c3b654fa0d160f3781271f0edbbb0ae50f285a91f2a272a09"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:64446f9baa2c51f47b0e272939c583ffd220e67f5bcbc2f18dd244c5a46a7018"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:a7b50fa86c1bd863ef3b3314da62928c015a732bb0aef220852b9606104f0df5"}, + {file = "zope.interface-4.7.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a9fce290a6ba88e5e6e81dd1e800c045212df69ab69d1de0d303b1af9cec692f"}, + {file = "zope.interface-4.7.2-cp35-cp35m-win32.whl", hash = "sha256:f044fec9c7e1b0ec6fdf0d3abc648c2f3b9128933051a9a73af52dbdd9e6d6e9"}, + {file = "zope.interface-4.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:23c4a70a9abb8faa35e2967e2e7cbd9225512b706b6eb96b01eb1ccbb2b632c3"}, + {file = "zope.interface-4.7.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:61b95dbfd03ce2a55c38da711cba7130605dbef4839ca12b53c46827826c5c5b"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:98a21acc7d1e45fcb700831b66ec6c84a3c2a5a94868d72ef83565966adc474f"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6f2bf246ee9350f428860c37db6158cfb27a7e585d60b2bb3b88864810875835"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b12241fac561b635329c3275e911a53e104b43875b99d31332d006d52e180912"}, + {file = "zope.interface-4.7.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7d3c4f10b7a8502a68a8eadcd57e86a35e3948af3edee7bd49a21b225361b0da"}, + {file = "zope.interface-4.7.2-cp36-cp36m-win32.whl", hash = "sha256:02339c53bbf7e438dec371af1f401e4843f9dc5765b3b032032b195dd72b47f2"}, + {file = "zope.interface-4.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:31fdcc9eaf2c379e8b416184a0749ce3f95fdaf206b092b63bdc065aecca6a95"}, + {file = "zope.interface-4.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9e67e9fa7dc43210ad766cd6eef133d9d256a530fe07e5585685cdc742170d10"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b906dda76ab70b6905ef3014260e7f1c861a0c4841e29826eb34a6187255504b"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:07de051fac6dedc6c659034f80bc46623edc776c757fa26f3f467954b12d2403"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36e7438d2f71153cea6b119ddd2648bc010cec4368fd8e7170e50090c0d7ed19"}, + {file = "zope.interface-4.7.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:4855384c27fe7e31efbee32f74659421d64e5bfa8b7df2ec08d306d0f3d4cee6"}, + {file = "zope.interface-4.7.2-cp37-cp37m-win32.whl", hash = "sha256:3b6a2ef2c6b4e9786939bd9861e7b98bc01cb3024f87c8cf4b78872f2afcf584"}, + {file = "zope.interface-4.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:eb92c733be08c6e2b8dfd4613d1b3c2f345ca4f83219d40fda4680333d3a0dc4"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:07a8bb9110854c0ab9329adbbec7050af242a78a62e226ab49e9c2182090f501"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:11db683f49652b34aa87904b27d00f9032fa2db7f1f9676c05b13361a3c7547c"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:65cef4766be4be9372621cd17773424302c21785dfaf6e9bd5b64b1f1264f9cc"}, + {file = "zope.interface-4.7.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:08ae0a88ac29b92faff069e0511ad27197b3274bdf67ebd8c75aaeb05823c7af"}, + {file = "zope.interface-4.7.2-cp38-cp38-win32.whl", hash = "sha256:993051db4278f9ec3b191ae823a7bb32b6a91fed6e960d43500fc4ce64cdb4e0"}, + {file = "zope.interface-4.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:d79da12a15edd6d7c366766954c4b6de0247e85ba35ee2ad9f37f972e7080f8a"}, + {file = "zope.interface-4.7.2.tar.gz", hash = "sha256:fd1101bd3fcb4f4cf3485bb20d6cb0b56909b94d3bd2a53a6cb9d381c3da3365"}, ] diff --git a/pyproject.toml b/pyproject.toml index f42f85d..411c1da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,11 +7,26 @@ license = "GPL-3.0-or-later" repository = "https://pagure.io/koji-fedmsg-plugin" homepage = "https://pagure.io/koji-fedmsg-plugin" +[tool.poetry.plugins."fedora.messages"] +"buildsys.repo.done"="koji_fedmsg_plugin.messages.repo:DoneV1" +"buildsys.repo.init"="koji_fedmsg_plugin.messages.repo:InitV1" +"buildsys.tag"="koji_fedmsg_plugin.messages.tag:TagV1" +"buildsys.untag"="koji_fedmsg_plugin.messages.tag:UntagV1" +"buildsys.build.state.change"="koji_fedmsg_plugin.messages.build:BuildStateChangeV1" +"buildsys.package.list.change"="koji_fedmsg_plugin.messages.package:ListChangeV1" +"buildsys.rpm.sign"="koji_fedmsg_plugin.messages.rpm:SignV1" +"buildsys.task.state.change"="koji_fedmsg_plugin.messages.task:TaskStateChangeV1" + [tool.poetry.dependencies] +python = "^3.6" fedora_messaging = "^2.0.1" koji = "^1.20.1" [tool.poetry.dev-dependencies] +pytest = "^5.4.1" +sphinx = "^2.4.4" +flake8 = "^3.7.9" +black = "^19.10b0" [build-system] requires = ["poetry>=0.12"]