remove python2 support from awxkit

This commit is contained in:
Ryan Petrello
2020-03-18 09:06:20 -04:00
parent db7f0f9421
commit 06b3e54fb1
18 changed files with 27 additions and 116 deletions

View File

@@ -1,8 +1,6 @@
from datetime import datetime from datetime import datetime
import json import json
import six
from awxkit.utils import poll_until from awxkit.utils import poll_until
from awxkit.exceptions import WaitUntilTimeout from awxkit.exceptions import WaitUntilTimeout
@@ -50,7 +48,7 @@ class HasStatus(object):
return self.wait_until_status(self.started_statuses, interval=interval, timeout=timeout) return self.wait_until_status(self.started_statuses, interval=interval, timeout=timeout)
def assert_status(self, status_list, msg=None): def assert_status(self, status_list, msg=None):
if isinstance(status_list, six.text_type): if isinstance(status_list, str):
status_list = [status_list] status_list = [status_list]
if self.status in status_list: if self.status in status_list:
# include corner cases in is_successful logic # include corner cases in is_successful logic

View File

@@ -1,6 +1,6 @@
import logging import logging
from six.moves import http_client as http import http.client as http
import awxkit.exceptions as exc import awxkit.exceptions as exc
from awxkit.api.mixins import DSAdapter, HasCopy, HasCreate from awxkit.api.mixins import DSAdapter, HasCopy, HasCreate
@@ -19,10 +19,7 @@ from awxkit.utils import (
from . import base, page from . import base, page
from .page import exception_from_status_code from .page import exception_from_status_code
try: from urllib.parse import urljoin
from urllib.parse import urljoin
except ImportError:
from urlparse import urljoin
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@@ -4,8 +4,7 @@ import json
import re import re
from requests import Response from requests import Response
import six import http.client as http
from six.moves import http_client as http
from awxkit.utils import ( from awxkit.utils import (
PseudoNamespace, PseudoNamespace,
@@ -170,10 +169,7 @@ class Page(object):
def from_json(cls, raw): def from_json(cls, raw):
resp = Response() resp = Response()
data = json.dumps(raw) data = json.dumps(raw)
if six.PY3: resp._content = bytes(data, 'utf-8')
resp._content = bytes(data, 'utf-8')
else:
resp._content = data
resp.encoding = 'utf-8' resp.encoding = 'utf-8'
resp.status_code = 200 resp.status_code = 200
return cls(r=resp) return cls(r=resp)

View File

@@ -6,7 +6,6 @@ import pkg_resources
import sys import sys
from requests.exceptions import RequestException from requests.exceptions import RequestException
import six
from .custom import handle_custom_actions from .custom import handle_custom_actions
from .format import (add_authentication_arguments, from .format import (add_authentication_arguments,
@@ -203,15 +202,7 @@ class CLI(object):
if hasattr(response, 'rc'): if hasattr(response, 'rc'):
raise SystemExit(response.rc) raise SystemExit(response.rc)
else: else:
if six.PY3: self.parser.print_help()
self.parser.print_help()
elif six.PY2 and not self.help:
# Unfortunately, argparse behavior between py2 and py3
# changed in a notable way when required subparsers
# have invalid (or missing) arguments specified
# see: https://github.com/python/cpython/commit/f97c59aaba2d93e48cbc6d25f7ff9f9c87f8d0b2
print('\nargument resource: invalid choice')
raise SystemExit(2)
def parse_action(self, page, from_sphinx=False): def parse_action(self, page, from_sphinx=False):
"""Perform an HTTP OPTIONS request """Perform an HTTP OPTIONS request

View File

@@ -1,8 +1,6 @@
import functools import functools
import json import json
from six import with_metaclass, PY3
from .stdout import monitor, monitor_workflow from .stdout import monitor, monitor_workflow
from .utils import CustomRegistryMeta, color_enabled from .utils import CustomRegistryMeta, color_enabled
from awxkit import api from awxkit import api
@@ -24,7 +22,7 @@ class CustomActionRegistryMeta(CustomRegistryMeta):
return ' '.join([self.resource, self.action]) return ' '.join([self.resource, self.action])
class CustomAction(with_metaclass(CustomActionRegistryMeta)): class CustomAction(metaclass=CustomActionRegistryMeta):
"""Base class for defining a custom action for a resource.""" """Base class for defining a custom action for a resource."""
def __init__(self, page): def __init__(self, page):
@@ -549,11 +547,8 @@ class SettingsModify(CustomAction):
return resp.from_json({'key': key, 'value': resp[key]}) return resp.from_json({'key': key, 'value': resp[key]})
def is_json(self, data): def is_json(self, data):
err = ValueError
if PY3:
err = json.decoder.JSONDecodeError
try: try:
json.loads(data) json.loads(data)
except err: except json.decoder.JSONDecodeError:
return False return False
return True return True

View File

@@ -2,7 +2,6 @@ import locale
import json import json
from distutils.util import strtobool from distutils.util import strtobool
import six
import yaml import yaml
from awxkit.cli.utils import colored from awxkit.cli.utils import colored
@@ -81,7 +80,7 @@ def add_output_formatting_arguments(parser, env):
def format_response(response, fmt='json', filter='.', changed=False): def format_response(response, fmt='json', filter='.', changed=False):
if response is None: if response is None:
return # HTTP 204 return # HTTP 204
if isinstance(response, six.text_type): if isinstance(response, str):
return response return response
if 'results' in response.__dict__: if 'results' in response.__dict__:
@@ -115,7 +114,7 @@ def format_jq(output, fmt):
results = [] results = []
for x in jq.jq(fmt).transform(output, multiple_output=True): for x in jq.jq(fmt).transform(output, multiple_output=True):
if x not in (None, ''): if x not in (None, ''):
if isinstance(x, six.text_type): if isinstance(x, str):
results.append(x) results.append(x)
else: else:
results.append(json.dumps(x)) results.append(json.dumps(x))

View File

@@ -7,7 +7,6 @@ import sys
import yaml import yaml
from distutils.util import strtobool from distutils.util import strtobool
import six
from .custom import CustomAction from .custom import CustomAction
from .format import add_output_formatting_arguments from .format import add_output_formatting_arguments
@@ -182,7 +181,7 @@ class ResourceOptionsParser(object):
for k, v in parsed.items(): for k, v in parsed.items():
# add support for file reading at top-level JSON keys # add support for file reading at top-level JSON keys
# (to make things like SSH key data easier to work with) # (to make things like SSH key data easier to work with)
if isinstance(v, six.text_type) and v.startswith('@'): if isinstance(v, str) and v.startswith('@'):
path = os.path.expanduser(v[1:]) path = os.path.expanduser(v[1:])
parsed[k] = open(path).read() parsed[k] = open(path).read()

View File

@@ -1,7 +1,5 @@
import os import os
from six import PY3, with_metaclass
from awxkit import api, config from awxkit import api, config
from awxkit.utils import to_str from awxkit.utils import to_str
from awxkit.api.pages import Page from awxkit.api.pages import Page
@@ -45,7 +43,7 @@ DEPRECATED_RESOURCES_REVERSE = dict(
) )
class CustomCommand(with_metaclass(CustomRegistryMeta)): class CustomCommand(metaclass=CustomRegistryMeta):
"""Base class for implementing custom commands. """Base class for implementing custom commands.
Custom commands represent static code which should run - they are Custom commands represent static code which should run - they are
@@ -153,18 +151,7 @@ def parse_resource(client, skip_deprecated=False):
k, help='', **kwargs k, help='', **kwargs
) )
try: resource = client.parser.parse_known_args()[0].resource
resource = client.parser.parse_known_args()[0].resource
except SystemExit:
if PY3:
raise
else:
# Unfortunately, argparse behavior between py2 and py3
# changed in a notable way when required subparsers
# have invalid (or missing) arguments specified
# see: https://github.com/python/cpython/commit/f97c59aaba2d93e48cbc6d25f7ff9f9c87f8d0b2
# In py2, this raises a SystemExit; which we want to _ignore_
resource = None
if resource in DEPRECATED_RESOURCES.values(): if resource in DEPRECATED_RESOURCES.values():
client.argv[ client.argv[
client.argv.index(resource) client.argv.index(resource)

View File

@@ -5,8 +5,6 @@ import os
import sys import sys
import threading import threading
import six
_color = threading.local() _color = threading.local()
_color.enabled = True _color.enabled = True
@@ -38,29 +36,6 @@ class CustomRegistryMeta(type):
class HelpfulArgumentParser(ArgumentParser): class HelpfulArgumentParser(ArgumentParser):
def __init__(self, *args, **kwargs):
super(HelpfulArgumentParser, self).__init__(*args, **kwargs)
if six.PY2:
# backport parser aliases support to py2
# see: https://github.com/python/cpython/commit/fd311a712d5876c3a3efff265978452eea759f85
SubParsersAction = self._registries['action']['parsers']
class _SubParsersAction(SubParsersAction):
def add_parser(self, name, **kwargs):
aliases = kwargs.pop('aliases', [])
parser = super(_SubParsersAction, self).add_parser(name, **kwargs)
if aliases:
self._choices_actions[-1].metavar = ' '.join([
name,
'({})'.format(', '.join(aliases))
])
for alias in aliases:
self._name_parser_map[alias] = parser
return parser
self._registries['action']['parsers'] = _SubParsersAction
def error(self, message): # pragma: nocover def error(self, message): # pragma: nocover
"""Prints a usage message incorporating the message to stderr and """Prints a usage message incorporating the message to stderr and
exits. exits.

View File

@@ -10,7 +10,6 @@ import sys
import re import re
import os import os
import six
import yaml import yaml
from awxkit.words import words from awxkit.words import words
@@ -132,7 +131,7 @@ class PseudoNamespace(dict):
def is_relative_endpoint(candidate): def is_relative_endpoint(candidate):
return isinstance(candidate, (six.text_type,)) and candidate.startswith('/api/') return isinstance(candidate, (str,)) and candidate.startswith('/api/')
def is_class_or_instance(obj, cls): def is_class_or_instance(obj, cls):
@@ -321,19 +320,9 @@ def update_payload(payload, fields, kwargs):
def to_str(obj): def to_str(obj):
if six.PY3: if isinstance(obj, bytes):
if isinstance(obj, bytes): return obj.decode('utf-8')
return obj.decode('utf-8') return obj
return obj
if not isinstance(obj, six.text_type):
try:
return str(obj)
except UnicodeDecodeError:
try:
obj = six.text_type(obj, 'utf8')
except UnicodeDecodeError:
obj = obj.decode('latin1')
return obj.encode('utf8')
def to_bool(obj): def to_bool(obj):

View File

@@ -4,8 +4,8 @@ import atexit
import json import json
import ssl import ssl
from six.moves.queue import Queue, Empty from queue import Queue, Empty
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
from awxkit.config import config from awxkit.config import config

View File

@@ -1,3 +1,2 @@
PyYAML PyYAML
requests requests
six

View File

@@ -67,7 +67,7 @@ setup(
}, },
include_package_data=True, include_package_data=True,
install_requires=requirements, install_requires=requirements,
python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*", python_requires=">=3.6",
extras_require={ extras_require={
'formatting': ['jq'], 'formatting': ['jq'],
'websockets': ['websocket-client>0.54.0'], 'websockets': ['websocket-client>0.54.0'],

View File

@@ -1,10 +1,7 @@
import argparse import argparse
import json import json
import unittest import unittest
try: from io import StringIO
from StringIO import StringIO
except ImportError:
from io import StringIO
import pytest import pytest
from requests import Response from requests import Response

View File

@@ -1,7 +1,4 @@
try: from unittest.mock import patch
from unittest.mock import patch
except ImportError:
from mock import patch
import pytest import pytest

View File

@@ -2,12 +2,8 @@
from datetime import datetime from datetime import datetime
import sys import sys
try: from unittest import mock
from unittest import mock
except ImportError:
import mock
import pytest import pytest
import six
from awxkit import utils from awxkit import utils
from awxkit import exceptions as exc from awxkit import exceptions as exc
@@ -83,7 +79,7 @@ def test_load_invalid_json_or_yaml(inp):
reason='this is only intended to be used in py3, not the CLI' reason='this is only intended to be used in py3, not the CLI'
) )
def test_random_titles_are_unicode(non_ascii): def test_random_titles_are_unicode(non_ascii):
assert isinstance(utils.random_title(non_ascii=non_ascii), six.text_type) assert isinstance(utils.random_title(non_ascii=non_ascii), str)
@pytest.mark.parametrize('non_ascii', [True, False]) @pytest.mark.parametrize('non_ascii', [True, False])

View File

@@ -1,10 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from collections import namedtuple from collections import namedtuple
try: from unittest.mock import patch
from unittest.mock import patch
except ImportError:
from mock import patch
import pytest import pytest
from awxkit.ws import WSClient from awxkit.ws import WSClient

View File

@@ -8,6 +8,7 @@ skip_missing_interpreters = true
# skipsdist = true # skipsdist = true
[testenv] [testenv]
basepython = python3.6
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
setenv = setenv =
PYTHONPATH = {toxinidir}:{env:PYTHONPATH:}:. PYTHONPATH = {toxinidir}:{env:PYTHONPATH:}:.
@@ -21,7 +22,6 @@ deps =
commands = coverage run --parallel --source awxkit -m pytest --doctest-glob='*.md' --junit-xml=report.xml {posargs} commands = coverage run --parallel --source awxkit -m pytest --doctest-glob='*.md' --junit-xml=report.xml {posargs}
[testenv:lint] [testenv:lint]
basepython = python3.6
deps = deps =
{[testenv]deps} {[testenv]deps}
flake8 flake8
@@ -32,7 +32,6 @@ commands =
- coverage erase - coverage erase
[testenv:coveralls] [testenv:coveralls]
basepython = python3.6
commands= commands=
- coverage combine - coverage combine
- coverage report -m - coverage report -m
@@ -43,4 +42,4 @@ max-line-length = 120
[pytest] [pytest]
addopts = -v --tb=native addopts = -v --tb=native
junit_family=xunit2 junit_family=xunit2