Skip to content

Commit

Permalink
Merge pull request #81 from BenjamenMeyer/enhancement_python-environm…
Browse files Browse the repository at this point in the history
…ent-updates

Enhancement: Update test environment and dependencies
  • Loading branch information
BenjamenMeyer authored Oct 23, 2019
2 parents 63ee457 + 61842e2 commit 8a02b3a
Show file tree
Hide file tree
Showing 22 changed files with 156 additions and 79 deletions.
38 changes: 21 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
language: python
matrix:
include:
- python: "2.7"
env: TEST_SUITE=suite_2_7 TOX_ENV=py27
- python: "pypy"
env: TEST_SUITE=suite_pypy TOX_ENV=pypy
- python: "3.4"
env: TEST_SUITE=suite_3_4 TOX_ENV=py34
- python: "pypy3"
env: TEST_SUITE=suite_pypy3 TOX_ENV=pypy3
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=pep8
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=docs
- python: "3.5"
env: TEST_SUITE=suite_3_4 TOX_ENV=py35
env: TEST_SUITE=suite_3_5 TOX_ENV=py35
- python: "3.7"
env: TEST_SUITE=suite_3_7 TOX_ENV=py37
- python: "3.8"
env: TEST_SUITE=suite_3_8 TOX_ENV=py38
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-httpretty
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-requests-mock
- python: "3.6"
env: TEST_SUITE=suite_3_4 TOX_ENV=py36
- python: "3.4"
env: TEST_SUITE=suite_3_4 TOX_ENV=pep8
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-responses
- python: "2.7"
env: TEST_SUITE=suite_2_7 TOX_ENV=docs
env: TEST_SUITE=suite_2_7 TOX_ENV=py27
- python: "2.7"
env: TEST_SUITE=suite_2_7 TOX_ENV=py27-httpretty
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-httpretty
- python: "2.7"
env: TEST_SUITE=suite_2_7 TOX_ENV=py27-requests-mock
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-requests-mock
- python: "2.7"
env: TEST_SUITE=suite_2_7 TOX_ENV=py27-responses
- python: "3.6"
env: TEST_SUITE=suite_3_6 TOX_ENV=py36-responses
- python: "pypy"
env: TEST_SUITE=suite_pypy TOX_ENV=pypy

sudo: required
before_install:
Expand Down
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ Out-of-the-box it supports the following frameworks:

You can use any of them, and you must pull them in via your own test requirements.

.. note:: HTTPretty has some version and Python limitations. Version 0.8.6 works fine; however, version 0.9.x which supports
Python3 seems to have a breaking change that is causing problems. Only 0.8.6 is supported by StackInABox under Python2
for the time being. That is not to say you may not get it to work; just that the StackInABox Unit Tests cannot verify it
will work. PRs are welcome to help resolve this. See Issue #80 for status.

-----------
Error Codes
-----------
Expand Down
2 changes: 1 addition & 1 deletion stackinabox/services/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def request(self, method, request, uri, headers):
return self.try_handle_route(uri, method, request, uri, headers)

def sub_request(self, method, request, uri, headers):
"""Handle the supplied sub-service request on the specified routing URI.
"""Handle the supplied sub-service request on the specified routing URI
:param method: string - HTTP Verb
:param request: request object describing the HTTP request
Expand Down
44 changes: 37 additions & 7 deletions stackinabox/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,42 @@ class StackInABox(object):
"""

@classmethod
def get_thread_instance(cls):
"""
Interface to the thread storage to ensure the instance properly exists
"""
create = False

# if the `instance` property doesn't exist
if not hasattr(local_store, 'instance'):
local_store.instance = None
create = True

# if the instance doesn't exist at all
elif local_store.instance is None:
create = True

# if it's something else entirely...
elif not isinstance(local_store.instance, cls):
local_store.instance = None
create = True

# if the above conditions are met, create it
if create:
logger.debug('Creating new StackInABox instance...')
local_store.instance = cls()
logger.debug(
'Created StackInABox({0})'.format(local_store.instance.__id)
)

return local_store.instance

@classmethod
def reset_services(cls):
"""Reset the thread's StackInABox instance."""
logger.debug('Resetting services')
return local_store.instance.reset()
return cls.get_thread_instance().reset()

@classmethod
def register_service(cls, service):
Expand All @@ -51,7 +82,7 @@ def register_service(cls, service):
"""
logger.debug('Registering service {0}'.format(service.name))
return local_store.instance.register(service)
return cls.get_thread_instance().register(service)

@classmethod
def call_into(cls, method, request, uri, headers):
Expand All @@ -66,7 +97,7 @@ def call_into(cls, method, request, uri, headers):
"""
logger.debug('Request: {0} - {1}'.format(method, uri))
return local_store.instance.call(method,
return cls.get_thread_instance().call(method,
request,
uri,
headers)
Expand All @@ -85,7 +116,7 @@ def hold_onto(cls, name, obj):
"""
logger.debug('Holding on {0} of type {1} with id {2}'
.format(name, type(obj), id(obj)))
local_store.instance.into_hold(name, obj)
cls.get_thread_instance().into_hold(name, obj)

@classmethod
def hold_out(cls, name):
Expand All @@ -102,7 +133,7 @@ def hold_out(cls, name):
"""
logger.debug('Retreiving {0} from hold'
.format(name))
obj = local_store.instance.from_hold(name)
obj = cls.get_thread_instance().from_hold(name)
logger.debug('Retrieved {0} of type {1} with id {2} from hold'
.format(name, type(obj), id(obj)))
return obj
Expand All @@ -115,7 +146,7 @@ def update_uri(cls, uri):
"""
logger.debug('Request: Update URI to {0}'.format(uri))
local_store.instance.base_url = uri
cls.get_thread_instance().base_url = uri

def __init__(self):
"""Initialize the StackInABox instance.
Expand Down Expand Up @@ -307,4 +338,3 @@ def from_hold(self, name):

# Thread local instance of StackInABox
local_store = threading.local()
local_store.instance = StackInABox()
2 changes: 1 addition & 1 deletion stackinabox/util/httpretty/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def registration(uri):

# build the regex for the uri and register all http verbs
# with httpretty
regex = re.compile('(http)?s?(://)?{0}:?(\d+)?/'.format(uri),
regex = re.compile(r'(http)?s?(://)?{0}:?(\d+)?/'.format(uri),
re.I)
for method in HttpBaseClass.METHODS:
register_uri(method, regex, body=httpretty_callback)
Expand Down
6 changes: 5 additions & 1 deletion stackinabox/util/httpretty/decorator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"""
Stack-In-A-Box: HTTPretty Support via decorator
"""
import collections
try:
import collections.abc as collections
except ImportError:
# Py2.7 Support
import collections
import functools
import logging
import re
Expand Down
2 changes: 1 addition & 1 deletion stackinabox/util/requests_mock/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(self, uri):
:param uri: URI to match against
"""
self.regex = re.compile(
'(http)?s?(://)?{0}:?(\d+)?/'.format(uri), re.I)
r'(http)?s?(://)?{0}:?(\d+)?/'.format(uri), re.I)

def __call__(self, request):
"""object callable interface.
Expand Down
6 changes: 5 additions & 1 deletion stackinabox/util/requests_mock/decorator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"""
Stack-In-A-Box: Requests-Mock Support via Decorator
"""
import collections
try:
import collections.abc as collections
except ImportError:
# Py2.7 Support
import collections
import functools
import logging
import re
Expand Down
2 changes: 1 addition & 1 deletion stackinabox/util/responses/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def registration(uri):

# Build the regex for the URI and register all HTTP verbs
# with Responses
regex = re.compile('(http)?s?(://)?{0}:?(\d+)?/'.format(uri),
regex = re.compile(r'(http)?s?(://)?{0}:?(\d+)?/'.format(uri),
re.I)
METHODS = [
responses.DELETE,
Expand Down
7 changes: 6 additions & 1 deletion stackinabox/util/responses/decorator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
"""
Stack-In-A-Box: Responses Support via decorator
"""
import collections
try:
import collections.abc as collections
except ImportError:
# Py2.7 Support
import collections

import functools
import logging
import re
Expand Down
6 changes: 5 additions & 1 deletion stackinabox/util/tools/caseinsensitivedict.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import collections
try:
import collections.abc as collections
except ImportError:
# Py2.7 Support
import collections


# Compliments of Requests
Expand Down
17 changes: 8 additions & 9 deletions tests/test_service.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import re
import unittest

import httpretty
import requests

from stackinabox.stack import StackInABox
from stackinabox.services.service import *
import stackinabox.util.httpretty
import stackinabox.util.requests_mock


class TestServiceRegex(unittest.TestCase):
Expand Down Expand Up @@ -112,7 +111,6 @@ def test_bad_registration(self):
service.register(StackInABoxService.GET, '/',
AnotherAdvancedService.second_handler)

@httpretty.activate
def test_subservice_registration(self):
service = AnotherAdvancedService()
subservice = YetAnotherService()
Expand All @@ -121,10 +119,11 @@ def test_subservice_registration(self):

StackInABox.register_service(service)

stackinabox.util.httpretty.registration('localhost')
with stackinabox.util.requests_mock.activate():
stackinabox.util.requests_mock.registration('localhost')

res = requests.get('http://localhost/aas/french')
self.assertEqual(res.status_code,
200)
self.assertEqual(res.text,
'bonjour')
res = requests.get('http://localhost/aas/french')
self.assertEqual(res.status_code,
200)
self.assertEqual(res.text,
'bonjour')
11 changes: 5 additions & 6 deletions tests/test_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
import unittest

import ddt
import httpretty
import requests

import stackinabox.util.httpretty
import stackinabox.util.requests_mock
from stackinabox.stack import (
StackInABox, ServiceAlreadyRegisteredError)
from stackinabox.services.service import *
Expand Down Expand Up @@ -52,12 +51,12 @@ def test_get_services_url(self, url, base, value):
result = StackInABox.get_services_url(url, base)
self.assertEqual(result, value)

@httpretty.activate
def test_service_exception(self):
exceptional = ExceptionalServices()
StackInABox.register_service(exceptional)

stackinabox.util.httpretty.registration('localhost')
with stackinabox.util.requests_mock.activate():
stackinabox.util.requests_mock.registration('localhost')

res = requests.get('http://localhost/except/')
self.assertEqual(res.status_code, 596)
res = requests.get('http://localhost/except/')
self.assertEqual(res.status_code, 596)
3 changes: 3 additions & 0 deletions tests/util/httpretty/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Stack-In-A-Box: Basic Test
"""
import logging
import sys
import unittest

import httpretty
Expand All @@ -18,6 +19,7 @@
logger = logging.getLogger(__name__)


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
@httpretty.activate
class TestHttprettyBasic(unittest.TestCase):

Expand All @@ -37,6 +39,7 @@ def test_basic(self):
self.assertEqual(res.text, 'Hello')


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
@httpretty.activate
class TestHttprettyAdvanced(unittest.TestCase):

Expand Down
5 changes: 5 additions & 0 deletions tests/util/httpretty/test_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Stack-In-A-Box: Basic Test
"""
import collections
import sys
import types
import unittest

Expand All @@ -13,6 +14,7 @@
from tests.utils.services import AdvancedService


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
class TestHttprettyBasicWithDecorator(unittest.TestCase):

@decorator.activate('localhost', HelloService())
Expand Down Expand Up @@ -41,6 +43,7 @@ def test_basic_with_stack_acccess(self, response_code, value='alpha',
self.assertIsInstance(stack[list(stack.keys())[0]], HelloService)


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
class TestHttprettyAdvancedWithDecorator(unittest.TestCase):

@decorator.activate('localhost', AdvancedService())
Expand Down Expand Up @@ -81,6 +84,7 @@ def httpretty_generator():
yield HelloService()


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
class TestHttprettyBasicWithDecoratorAndGenerator(unittest.TestCase):

def test_verify_generator(self):
Expand Down Expand Up @@ -127,6 +131,7 @@ def httpretty_list():
]


@unittest.skipIf(sys.version_info >= (3, 0), "Httpretty not supported by Py3")
class TestHttprettyBasicWithDecoratorAndList(unittest.TestCase):

def test_verify_list(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/utils/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self):
self.register(StackInABoxService.GET, '/g',
AdvancedService.query_handler)
self.register(StackInABoxService.GET,
re.compile('^/\d+$'),
re.compile(r'^/\d+$'),
AdvancedService.regex_handler)

for key in self.POTENTIAL_RESPONSES.keys():
Expand Down
Loading

0 comments on commit 8a02b3a

Please sign in to comment.