Skip to content

Commit

Permalink
2024 Updates
Browse files Browse the repository at this point in the history
- Drop Python 2.7 support and add word of caution about Pypy and
  setuptools
- Update note about CI systems to include 4th gen systems (e.g
  GitHub Actions)
- Convert from setup.py to setup.cfg using the newer methodology
  so no parameters are specified to `setup()`
- Update the `version` test that ensures the code and installation
  version match to use `subprocess` to inspect the output of
  `pip show stackinabox` instead of importing `setup.py` as
  `setup.py` no longer contains the data it was searching for
- Fix several tests where the query parameters were separated by
  both `;` and `&` and it should have only separated on `&`
- Update the dependencies to latest stable versions
  • Loading branch information
BenjamenMeyer committed Feb 11, 2024
1 parent bf25972 commit f36378c
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 97 deletions.
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Installation is simple:
pip install stackinabox
.. note:: Python 2.7 is no longer supported. Pypy implements Python2.7 compatibility, however, the `setuptools` package
may cause issues if you cannot install a version that supports Python2.7.

=====
Goals
=====
Expand All @@ -40,7 +43,7 @@ Goals
- you should not necessarily need to know the ins and outs of each service
- you should be able to register what you need (f.e authentication, storage) and have it just work

- should be useable on systems like Travis (https://travis-ci.org/)
- should be useable on systems like Travis (https://travis-ci.org/), GitHub Actions, etc
- should be light on requirements

- we do not want to bloat your testing to fit our needs
Expand Down
30 changes: 30 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,33 @@ cover-erase=1
cover-inclusive=true
cover-branches=true
cover-min-percentage=92

[metadata]
name = stackinabox
url = https://github.com/TestInABox/stackInABox
version = attr: stackinabox.version
author = Benjamen R. Meyer
author_email = [email protected]
description = RESTful API Testing Suite
long_description = file: README.rst, LICENSE, CONTRIBUTING.rst
license = Apache License 2.0
classifiers =
Intended Audience :: Developers
License :: OSI Approved :: Apache Software License
Topic :: Software Development :: Testing

[options]
zip_safe = True
packages = find:
install_requires =
six

[options.extras_require]
httpretty = httpretty==1.1.4
requests-mock = requests-mock
responses = responses>=0.4.0

[options.packages.find]
exclude =
test*
stackinabox/tests
28 changes: 2 additions & 26 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
import sys
from setuptools import setup, find_packages
from setuptools import setup

REQUIRES = ['six']
EXTRA_REQUIRES = {
'httpretty': ['httpretty==0.8.6'],
'requests-mock': ['requests-mock'],
'responses': ['responses>=0.4.0']
}

setup(
name='stackinabox',
version='0.13',
description='RESTful API Testing Suite',
license='Apache License 2.0',
url='https://github.com/TestInABox/stackInABox',
author='Benjamen R. Meyer',
author_email='[email protected]',
install_requires=REQUIRES,
extras_require=EXTRA_REQUIRES,
test_suite='stackinabox',
packages=find_packages(exclude=['tests*', 'stackinabox/tests']),
zip_safe=True,
classifiers=["Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Topic :: Software Development :: Testing"],
)
setup()
25 changes: 18 additions & 7 deletions tests/test_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import os.path
import subprocess
import sys

import stackinabox
Expand All @@ -11,7 +12,6 @@ class TestVersionMatch(base.TestCase):
def setUp(self):
super(TestVersionMatch, self).setUp()
self.local_directory = os.path.dirname(__file__)
self.setup_py = '{0}/../setup.py'.format(self.local_directory)
self.doc_conf = '{0}/../../docs/conf.py'.format(self.local_directory)

def tearDown(self):
Expand All @@ -27,14 +27,25 @@ def make_version_source():
def test_version_match(self):
version_source = self.make_version_source()

# read the data from `pip show <package>` to get the version
# as seen by the installer
version_setup = None
with open(self.setup_py, 'rt') as input_data:
for line in input_data:
ln = line.strip()
if ln.startswith('version='):
ln_parts = ln.replace("'", '', 2).replace(',', '')
version_setup = ln_parts.split('=')[1]
cmd = ["pip", "show", "stackinabox"]
pip_freeze = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output, error = pip_freeze.communicate()
if error is None:
output_lines = output.decode('utf-8').split("\n")
print(f"Read pip freeze data:\n{output_lines}\n")
for line in output_lines:
line_data = line.split(':')
key = line_data[0]
value = ':'.join(line_data[1:]).strip()
print(f"\tLine Key: {key} - Value: {value}")
if key.lower() == "version":
version_setup = value
break
else:
self.fail(f"Unable to retrieve version data - error: {error}")

self.assertEqual(version_source, version_setup)

Expand Down
10 changes: 6 additions & 4 deletions tests/util/requests_mock/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ def test_basic(self):
'alice': 'alice: Good-Bye bob',
'joe': 'joe: Good-Bye jane'
}
res = self.session.get('http://localhost/advanced/g?bob=alice;'
'alice=bob&joe=jane')
res = self.session.get(
'http://localhost/advanced/g?bob=alice&alice=bob&joe=jane'
)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.json(), expected_result)

Expand Down Expand Up @@ -185,8 +186,9 @@ def test_context_requests_mock(self):
'alice': 'alice: Good-Bye bob',
'joe': 'joe: Good-Bye jane'
}
res = requests.get('http://localhost/advanced/g?bob=alice;'
'alice=bob&joe=jane')
res = requests.get(
'http://localhost/advanced/g?bob=alice&alice=bob&joe=jane'
)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.json(), expected_result)

Expand Down
5 changes: 3 additions & 2 deletions tests/util/requests_mock/test_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ def test_basic(self, session):
'alice': 'alice: Good-Bye bob',
'joe': 'joe: Good-Bye jane'
}
res = session.get('http://localhost/advanced/g?bob=alice;'
'alice=bob&joe=jane')
res = session.get(
'http://localhost/advanced/g?bob=alice&alice=bob&joe=jane'
)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.json(), expected_result)

Expand Down
5 changes: 3 additions & 2 deletions tests/util/response/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ def run(use_deprecated):
'alice': 'alice: Good-Bye bob',
'joe': 'joe: Good-Bye jane'
}
res = requests.get('http://localhost/advanced/g?bob=alice;'
'alice=bob&joe=jane')
res = requests.get(
'http://localhost/advanced/g?bob=alice&alice=bob&joe=jane'
)
assert res.status_code == 200
assert res.json() == expected_result

Expand Down
5 changes: 3 additions & 2 deletions tests/util/response/test_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ def test_advanced_responses():
'alice': 'alice: Good-Bye bob',
'joe': 'joe: Good-Bye jane'
}
res = requests.get('http://localhost/advanced/g?bob=alice;'
'alice=bob&joe=jane')
res = requests.get(
'http://localhost/advanced/g?bob=alice&alice=bob&joe=jane'
)
assert res.status_code == 200
assert res.json() == expected_result

Expand Down
12 changes: 6 additions & 6 deletions tools/docs-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
doc8==0.8.1
httpretty==1.0.5
requests==2.25.1
requests-mock==1.8.0
doc8==1.1.1
httpretty==1.1.4
requests==2.31.0
requests-mock==1.11.0
responses>=0.12.1
six==1.15.0
sphinx==3.4.2
six==1.16.0
sphinx==7.2.6
2 changes: 1 addition & 1 deletion tools/pep8-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
setuptools>=1.1.6
pycodestyle==2.6.0
pycodestyle==2.11.1
25 changes: 13 additions & 12 deletions tools/py2-test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
coverage==4.5.4
ddt==1.2.1
httpretty==0.8.6
mock==3.0.5
pytest==3.3.2
pytest-cov==2.5.1
requests==2.22.0
requests-mock==1.7.0
responses>=0.10.6
six==1.12.0
pycodestyle==2.5.0
attrs==17.2.0
coverage==7.4.1
ddt==1.7.1
httpretty==1.1.4
mock==5.1.0
pytest==8.0.0
pytest-cov==4.1.0
requests==2.31.0
requests-mock==1.11.0
responses>=0.12.1
six==1.16.0
pycodestyle==2.11.1
attrs==23.2.0
setuptools<=44.1.1
20 changes: 10 additions & 10 deletions tools/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
coverage==5.3.1
ddt==1.4.1
httpretty==1.0.5
mock==4.0.3
pytest==6.2.1
pytest-cov==2.10.1
requests==2.25.1
requests-mock==1.8.0
coverage==7.4.1
ddt==1.7.1
httpretty==1.1.4
mock==5.1.0
pytest==8.0.0
pytest-cov==4.1.0
requests==2.31.0
requests-mock==1.11.0
responses>=0.12.1
six==1.15.0
pycodestyle==2.6.0
six==1.16.0
pycodestyle==2.11.1
importlib-metadata==3.3.0 ;python_version<"3.8"
32 changes: 8 additions & 24 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,64 +1,48 @@
[tox]
minversion=1.8
envlist = {py3.6,py3.7,py3.8,py3.9},py3-httpretty,py3-requests-mock,py3-responses,pep8,docs
envlist = {py3.8,py3.9,py3.10,py3.11,py3.12},py3-httpretty,py3-requests-mock,py3-responses,pep8,docs
skip_missing_interpreters=True

[testenv]
basepython =
py27: python2.7
pypy: pypy
pypy3: pypy3
py35: python3.5
py3.6: python3.6
py3.7: python3.7
py3.8: python3.8
py3.9: python3.9
py3.10: python3.10
py3.11: python3.11
py3.12: python3.12
pep8: python3
docs: python3
deps =
py27,pypy: -r{toxinidir}/tools/py2-test-requirements.txt
pypy3,py35,py3.6,py3.7,py3.8,py3.9,docs: -r{toxinidir}/tools/test-requirements.txt
pypy: -r{toxinidir}/tools/py2-test-requirements.txt
pypy3,py3.8,py3.9,py3.10,py3.11,py3.12,docs: -r{toxinidir}/tools/test-requirements.txt
pep8: -r{toxinidir}/tools/pep8-requirements.txt
docs: -r{toxinidir}/tools/docs-requirements.txt
commands =
py27,pypy,pypy3,py35,py3.6,py3.7,py3.8,py3.9: pytest {toxinidir}/tests --cov-config=.coveragerc --cov=stackinabox {posargs}
pypy,pypy3,py3.8,py3.9,py3.10,py3.11,py3.12: pytest {toxinidir}/tests --cov-config=.coveragerc --cov=stackinabox {posargs}
pep8: pycodestyle --exclude=.tox,dist,doc,docs,*env*,.*env*,build --ignore=E128,W504
docs: sphinx-build -b html -d {envtmpdir}/doctrees docs docs/_build/html
docs: sphinx-build -b latex -d {envtmpdir}/doctrees docs docs/_build/latex
docs: sphinx-build -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
docs: doc8 --allow-long-titles docs/
setenv =
pypy3,py35,py3.6,py3.7,py3.8,py3.9,py3-httpretty,py3-requests-mock,py3-responses: VIRTUAL_ENV={envdir} LC_ALL = en_US.utf-8
pypy3,py3.8,py3.9,py3.10,py3.11,py3.12,py3-httpretty,py3-requests-mock,py3-responses: VIRTUAL_ENV={envdir} LC_ALL = en_US.utf-8

# Unfortunately the below doesn't seem to integrate well into the form above
# but it's valuable for testing the setup with extra dependencies to make sure things install right
[testenv:py27-httpretty]
basepython = python2.7
deps = .[httpretty]
commands = python -c "import stackinabox.util.httpretty"

[testenv:py3-httpretty]
basepython = python3
deps = .[httpretty]
commands = python -c "import stackinabox.util.httpretty"
setenv ={envdir} LC_ALL = en_US.utf-8

[testenv:py27-requests-mock]
basepython = python2.7
deps = .[requests-mock]
commands = python -c "import stackinabox.util.requests_mock"

[testenv:py3-requests-mock]
basepython = python3
deps = .[requests-mock]
commands = python -c "import stackinabox.util.requests_mock"
setenv ={envdir} LC_ALL = en_US.utf-8

[testenv:py27-responses]
basepython = python2.7
deps = .[responses]
commands = python -c "import stackinabox.util.responses"

[testenv:py3-responses]
basepython = python3
deps = .[responses]
Expand Down

0 comments on commit f36378c

Please sign in to comment.