Skip to content

Commit 180ee00

Browse files
Merge pull request #817 from hugapi/develop
Release 2.5.6
2 parents 8f71844 + 2295257 commit 180ee00

16 files changed

+95
-34
lines changed

Diff for: .bumpversion.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 2.5.5
2+
current_version = 2.5.6
33

44
[bumpversion:file:.env]
55

Diff for: .coveragerc

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ exclude_lines = def hug
77
sys.stdout.buffer.write
88
class Socket
99
pragma: no cover
10+
except ImportError:
11+
if MARSHMALLOW_MAJOR_VERSION is None or MARSHMALLOW_MAJOR_VERSION == 2:

Diff for: .env

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fi
1111

1212
export PROJECT_NAME=$OPEN_PROJECT_NAME
1313
export PROJECT_DIR="$PWD"
14-
export PROJECT_VERSION="2.5.5"
14+
export PROJECT_VERSION="2.5.6"
1515

1616
if [ ! -d "venv" ]; then
1717
if ! hash pyvenv 2>/dev/null; then

Diff for: ACKNOWLEDGEMENTS.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Code Contributors
5151
- Stanislav (@atmo)
5252
- Lordran (@xzycn)
5353
- Stephan Fitzpatrick (@knowsuchagency)
54-
54+
- Edvard Majakari (@EdvardM)
5555

5656
Documenters
5757
===================

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Ideally, within a virtual environment.
1111

1212
Changelog
1313
=========
14+
### 2.5.6 - June 20, 2019
15+
- Fixed issue #815: map_params() causes api documentation to lose param type information
16+
- Improved project testing: restoring 100% coverage
17+
1418
### 2.5.5 - June 13, 2019
1519
- Fixed issue #808: Problems with command line invocation via hug CLI
1620
- Fixed issue #647: Support for arbitrary URL complexity when using CORS middleware

Diff for: hug/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
"""
2222
from __future__ import absolute_import
2323

24-
current = "2.5.5"
24+
current = "2.5.6"

Diff for: hug/api.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,7 @@ def version_router(
348348
self, request, response, api_version=None, versions=None, not_found=None, **kwargs
349349
):
350350
"""Intelligently routes a request to the correct handler based on the version being requested"""
351-
if versions is None:
352-
versions = {}
351+
versions = {} if versions is None else versions
353352
request_version = self.determine_version(request, api_version)
354353
if request_version:
355354
request_version = int(request_version)

Diff for: hug/interface.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ def __init__(self, route, function):
212212
for name, transform in self.interface.input_transformations.items()
213213
}
214214
else:
215+
self.map_params = {}
215216
self.input_transformations = self.interface.input_transformations
216217

217218
if "output" in route:
@@ -323,7 +324,7 @@ def documentation(self, add_to=None):
323324
inputs = doc.setdefault("inputs", OrderedDict())
324325
types = self.interface.spec.__annotations__
325326
for argument in parameters:
326-
kind = types.get(argument, text)
327+
kind = types.get(self._remap_entry(argument), text)
327328
if getattr(kind, "directive", None) is True:
328329
continue
329330

@@ -340,6 +341,9 @@ def _rewrite_params(self, params):
340341
if interface_name in params:
341342
params[internal_name] = params.pop(interface_name)
342343

344+
def _remap_entry(self, interface_name):
345+
return self.map_params.get(interface_name, interface_name)
346+
343347
@staticmethod
344348
def cleanup_parameters(parameters, exception=None):
345349
for _parameter, directive in parameters.items():
@@ -417,8 +421,7 @@ def __call__(self, *args, **kwargs):
417421
self.api.delete_context(context, errors=errors)
418422
return outputs(errors) if outputs else errors
419423

420-
if getattr(self, "map_params", None):
421-
self._rewrite_params(kwargs)
424+
self._rewrite_params(kwargs)
422425
try:
423426
result = self.interface(**kwargs)
424427
if self.transform:
@@ -617,8 +620,7 @@ def exit_callback(message):
617620
elif add_options_to:
618621
pass_to_function[add_options_to].append(option)
619622

620-
if getattr(self, "map_params", None):
621-
self._rewrite_params(pass_to_function)
623+
self._rewrite_params(pass_to_function)
622624

623625
try:
624626
if args:
@@ -816,8 +818,7 @@ def call_function(self, parameters):
816818
parameters = {
817819
key: value for key, value in parameters.items() if key in self.all_parameters
818820
}
819-
if getattr(self, "map_params", None):
820-
self._rewrite_params(parameters)
821+
self._rewrite_params(parameters)
821822

822823
return self.interface(**parameters)
823824

@@ -854,7 +855,7 @@ def render_content(self, content, context, request, response, **kwargs):
854855
if size:
855856
response.set_stream(content, size)
856857
else:
857-
response.stream = content
858+
response.stream = content # pragma: no cover
858859
else:
859860
response.data = content
860861

Diff for: hug/routing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def allow_origins(
317317
response_headers = {}
318318
if origins:
319319

320-
@hug.response_middleware()
320+
@hug.response_middleware(api=self.route.get("api", None))
321321
def process_data(request, response, resource):
322322
if "ORIGIN" in request.headers:
323323
origin = request.headers["ORIGIN"]

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def list_modules(dirname):
7878

7979
setup(
8080
name="hug",
81-
version="2.5.5",
81+
version="2.5.6",
8282
description="A Python framework that makes developing APIs "
8383
"as simple as possible, but no simpler.",
8484
long_description=long_description,

Diff for: tests/test_decorators.py

+13-11
Original file line numberDiff line numberDiff line change
@@ -1042,17 +1042,14 @@ def extend_with():
10421042
def extend_with():
10431043
return (tests.module_fake_http_and_cli,)
10441044

1045-
assert hug.test.cli("sub_api", "made_up_go", api=api)
1046-
10471045
# But not both
10481046
with pytest.raises(ValueError):
1049-
10501047
@hug.extend_api(sub_command="sub_api", command_prefix="api_", http=False)
10511048
def extend_with():
10521049
return (tests.module_fake_http_and_cli,)
10531050

10541051

1055-
def test_extending_api_with_http_and_cli():
1052+
def test_extending_api_with_http_and_cli_sub_module():
10561053
"""Test to ensure it's possible to extend the current API so both HTTP and CLI APIs are extended"""
10571054
import tests.module_fake_http_and_cli
10581055

@@ -1579,20 +1576,25 @@ def test_multiple_cli(ints: hug.types.Multiple[int]() = []):
15791576
assert hug.test.cli(test_multiple_cli, ints=["1", "2", "3"]) == [1, 2, 3]
15801577

15811578

1582-
def test_startup():
1579+
def test_startup(hug_api):
15831580
"""Test to ensure hug startup decorators work as expected"""
1581+
happened_on_startup = []
15841582

1585-
@hug.startup()
1583+
@hug.startup(api=hug_api)
15861584
def happens_on_startup(api):
1587-
pass
1585+
happened_on_startup.append("non-async")
15881586

1589-
@hug.startup()
1587+
@hug.startup(api=hug_api)
15901588
@asyncio.coroutine
15911589
def async_happens_on_startup(api):
1592-
pass
1590+
happened_on_startup.append("async")
1591+
1592+
assert happens_on_startup in hug_api.startup_handlers
1593+
assert async_happens_on_startup in hug_api.startup_handlers
15931594

1594-
assert happens_on_startup in api.startup_handlers
1595-
assert async_happens_on_startup in api.startup_handlers
1595+
hug_api._ensure_started()
1596+
assert "async" in happened_on_startup
1597+
assert "non-async" in happened_on_startup
15961598

15971599

15981600
@pytest.mark.skipif(sys.platform == "win32", reason="Currently failing on Windows build")

Diff for: tests/test_documentation.py

+8
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,11 @@ def marshtest() -> Returns():
185185
doc = api.http.documentation()
186186

187187
assert doc["handlers"]["/marshtest"]["POST"]["outputs"]["type"] == "Return docs"
188+
189+
def test_map_params_documentation_preserves_type():
190+
@hug.get(map_params={"from": "from_mapped"})
191+
def map_params_test(from_mapped: hug.types.number):
192+
pass
193+
194+
doc = api.http.documentation()
195+
assert doc["handlers"]["/map_params_test"]["GET"]["inputs"]["from"]["type"] == "A whole number"

Diff for: tests/test_main.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""tests/test_main.py.
2+
3+
Basic testing of hug's `__main__` module
4+
5+
Copyright (C) 2016 Timothy Edmund Crosley
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9+
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
10+
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all copies or
13+
substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
16+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
18+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19+
OTHER DEALINGS IN THE SOFTWARE.
20+
21+
"""
22+
import pytest
23+
24+
25+
def test_main(capsys):
26+
"""Main module should be importable, but should raise a SystemExit after CLI docs print"""
27+
with pytest.raises(SystemExit):
28+
from hug import __main__

Diff for: tests/test_routing.py

+13
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,16 @@ def test_prefixes(self):
406406
def test_suffixes(self):
407407
"""Test to ensure setting suffixes works as expected"""
408408
assert self.route.suffixes(".js", ".xml").route["suffixes"] == (".js", ".xml")
409+
410+
def test_allow_origins_request_handling(self, hug_api):
411+
"""Test to ensure a route with allowed origins works as expected"""
412+
route = URLRouter(api=hug_api)
413+
test_headers = route.allow_origins(
414+
"google.com", methods=("GET", "POST"), credentials=True, headers="OPTIONS", max_age=10
415+
)
416+
417+
@test_headers.get()
418+
def my_endpoint():
419+
return "Success"
420+
421+
assert hug.test.get(hug_api, "/my_endpoint", headers={'ORIGIN': 'google.com'}).data == "Success"

Diff for: tests/test_types.py

+4
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ def test_json():
320320
with pytest.raises(ValueError):
321321
hug.types.json("Invalid JSON")
322322

323+
assert hug.types.json(json.dumps(["a", "b"]).split(",")) == ["a", "b"]
324+
with pytest.raises(ValueError):
325+
assert hug.types.json(["Invalid JSON", "Invalid JSON"])
326+
323327

324328
def test_multi():
325329
"""Test to ensure that the multi type correctly handles a variety of value types"""

Diff for: tox.ini

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@ envlist=py{35,36,37,py3}-marshmallow{2,3}, cython-marshmallow{2,3}
55
deps=
66
-rrequirements/build_common.txt
77
marshmallow2: marshmallow <3.0
8-
marshmallow3: marshmallow >=3.0.0rc5
8+
marshmallow3: marshmallow==3.0.0rc6
99

1010
whitelist_externals=flake8
11-
commands=py.test --cov-report html --cov hug -n auto tests
11+
commands=py.test --durations 3 --cov-report html --cov hug -n auto tests
1212

1313
[testenv:py37-black]
1414
deps=
1515
-rrequirements/build_style_tools.txt
16-
marshmallow >=3.0.0rc5
16+
marshmallow==3.0.0rc6
1717

1818
whitelist_externals=flake8
1919
commands=black --check --verbose -l 100 hug
2020

2121
[testenv:py37-vulture]
2222
deps=
2323
-rrequirements/build_style_tools.txt
24-
marshmallow >=3.0.0rc5
24+
marshmallow==3.0.0rc6
2525

2626
whitelist_externals=flake8
2727
commands=vulture hug --min-confidence 100 --ignore-names req_succeeded
@@ -30,23 +30,23 @@ commands=vulture hug --min-confidence 100 --ignore-names req_succeeded
3030
[testenv:py37-flake8]
3131
deps=
3232
-rrequirements/build_style_tools.txt
33-
marshmallow >=3.0.0rc5
33+
marshmallow==3.0.0rc6
3434

3535
whitelist_externals=flake8
3636
commands=flake8 hug
3737

3838
[testenv:py37-bandit]
3939
deps=
4040
-rrequirements/build_style_tools.txt
41-
marshmallow >=3.0.0rc5
41+
marshmallow==3.0.0rc6
4242

4343
whitelist_externals=flake8
4444
commands=bandit -r hug/ -ll
4545

4646
[testenv:py37-isort]
4747
deps=
4848
-rrequirements/build_style_tools.txt
49-
marshmallow >=3.0.0rc5
49+
marshmallow==3.0.0rc6
5050

5151
whitelist_externals=flake8
5252
commands=isort -c --diff --recursive hug

0 commit comments

Comments
 (0)