simplify awxkit dependencies

- remove flake8 as an install requirements (it's only used for tests)
- vendor toposort, which is Apache 2.0 licensed (and very small)
- change websocket-client to a setuptools optional dependency, which you
  can install via:

  pip install "./awxkit[websockets]"

- add `jq` and `tabulate` under an additional optional setuptools
  dependency:

  pip install "./awxkit[formatting]"

- remove `cryptography`, which is only used for random RSA generation
  (unused by the CLI)
This commit is contained in:
Ryan Petrello 2019-08-12 16:41:31 -04:00
parent 0b112e5b8f
commit 299fa3b6b4
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
9 changed files with 96 additions and 13 deletions

View File

@ -1,9 +1,8 @@
from collections import defaultdict
import inspect
from toposort import toposort
from awxkit.utils import get_class_if_instance, class_name_to_kw_arg, is_proper_subclass, super_dir_set
from awxkit.utils.toposort import toposort
# HasCreate dependency resolution and creation utilities

View File

@ -1,10 +1,6 @@
import logging
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from awxkit.utils import (
cloud_types,
filter_by_class,
@ -47,6 +43,10 @@ credential_input_fields = (
def generate_private_key():
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,

View File

@ -0,0 +1,82 @@
#######################################################################
# Implements a topological sort algorithm.
#
# Copyright 2014 True Blade Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Notes:
# Based on http://code.activestate.com/recipes/578272-topological-sort
# with these major changes:
# Added unittests.
# Deleted doctests (maybe not the best idea in the world, but it cleans
# up the docstring).
# Moved functools import to the top of the file.
# Changed assert to a ValueError.
# Changed iter[items|keys] to [items|keys], for python 3
# compatibility. I don't think it matters for python 2 these are
# now lists instead of iterables.
# Copy the input so as to leave it unmodified.
# Renamed function from toposort2 to toposort.
# Handle empty input.
# Switch tests to use set literals.
#
########################################################################
from functools import reduce as _reduce
__all__ = ['toposort', 'CircularDependencyError']
class CircularDependencyError(ValueError):
def __init__(self, data):
# Sort the data just to make the output consistent, for use in
# error messages. That's convenient for doctests.
s = 'Circular dependencies exist among these items: {{{}}}'.format(', '.join('{!r}:{!r}'.format(key, value) for key, value in sorted(data.items()))) # noqa
super(CircularDependencyError, self).__init__(s)
self.data = data
def toposort(data):
"""Dependencies are expressed as a dictionary whose keys are items
and whose values are a set of dependent items. Output is a list of
sets in topological order. The first set consists of items with no
dependences, each subsequent set consists of items that depend upon
items in the preceeding sets.
"""
# Special case empty input.
if len(data) == 0:
return
# Copy the input so as to leave it unmodified.
data = data.copy()
# Ignore self dependencies.
for k, v in data.items():
v.discard(k)
# Find all items that don't depend on anything.
extra_items_in_deps = _reduce(set.union, data.values()) - set(data.keys())
# Add empty dependences where needed.
data.update({item: set() for item in extra_items_in_deps})
while True:
ordered = set(item for item, dep in data.items() if len(dep) == 0)
if not ordered:
break
yield ordered
data = {
item: (dep - ordered)
for item, dep in data.items() if item not in ordered
}
if len(data) != 0:
raise CircularDependencyError(data)

View File

@ -7,8 +7,6 @@ import json
import ssl
import urllib.parse
import websocket
from awxkit.config import config
@ -53,6 +51,9 @@ class WSClient(object):
# Subscription group types
def __init__(self, token=None, hostname='', port=443, secure=True, session_id=None, csrftoken=None):
# delay this import, because this is an optional dependency
import websocket
if not hostname:
result = urllib.parse.urlparse(config.base_url)
secure = result.scheme == 'https'

View File

@ -1,8 +1,4 @@
PyYAML>=5.1
cryptography
flake8
python-dateutil
requests
termcolor
toposort
websocket-client>=0.54.0

View File

@ -68,6 +68,10 @@ setup(
include_package_data=True,
install_requires=requirements,
python_requires=">= 3.5",
extras_require={
'formatting': ['jq', 'tabulate'],
'websockets': ['websocket-client>0.54.0'],
},
entry_points={
'console_scripts': [
'akit=awxkit.scripts.basic_session:load_interactive',

View File

@ -1,7 +1,7 @@
from toposort import CircularDependencyError
import pytest
from awxkit.utils import filter_by_class
from awxkit.utils.toposort import CircularDependencyError
from awxkit.api.mixins import has_create

View File

@ -12,6 +12,7 @@ passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
setenv =
PYTHONPATH = {toxinidir}:{env:PYTHONPATH:}:.
deps =
websocket-client
coverage
pytest
pytest-mock