Skip to content

Commit 4a33366

Browse files
committed
Merge branch 'release/0.8.38'
2 parents ed0d508 + 05adf2f commit 4a33366

File tree

9 files changed

+86
-9
lines changed

9 files changed

+86
-9
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ branches:
66

77
python:
88
- "2.7"
9-
- "3.3"
9+
- "3.4"
1010
- "3.5"
1111
- "3.6"
1212
install:

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## Changes
22

3+
### 0.8.38
4+
5+
- Allow to access headers with case insensitive keys
6+
- Drop support to py3.3 because of Tornado
7+
38
### 0.8.37
49

510
- Fix loading error on 'yaml' document

pyswagger/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '0.8.37'
1+
__version__ = '0.8.38'
22

33
from .getter import Getter
44
from .core import App, Security

pyswagger/io.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import absolute_import
22
from .primitives.comm import PrimJSONEncoder
3-
from .utils import final, deref
3+
from .utils import final, deref, CaseInsensitiveDict
44
from pyswagger import errs
55
from uuid import uuid4
66
import six
@@ -33,7 +33,7 @@ def __init__(self, op, params):
3333
self.__p = params
3434
self.__url = self.__op.url
3535
self.__path = self.__op.path
36-
self.__header = {}
36+
self.__header = CaseInsensitiveDict()
3737

3838
self.__consume = None
3939
self.__produce = None
@@ -42,7 +42,7 @@ def __init__(self, op, params):
4242
def reset(self):
4343
self.__url = self.__op.url
4444
self.__path = self.__op.path
45-
self.__header = {}
45+
self.__header = CaseInsensitiveDict()
4646
self.__data = None
4747

4848
def consume(self, consume):
@@ -350,7 +350,7 @@ def __init__(self, op):
350350

351351
# init properties
352352
self.__status = None
353-
self.__header = {}
353+
self.__header = CaseInsensitiveDict()
354354

355355
# options
356356
self.__raw_body_only = False

pyswagger/primitives/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ def __init__(self):
9090

9191
def get(self, _type, _format=None):
9292
r = self._map.get(_type, None)
93-
return (None, None) if r == None else r.get(_format, (None, None))
93+
if r is None:
94+
return (None, None)
95+
if _format in r:
96+
return r.get(_format)
97+
return r.get(None)
9498

9599
def register(self, _type, _format, creater, _2nd_pass=None):
96100
""" register a type/format handler when producing primitives

pyswagger/primitives/_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def __init__(self):
1515
super(Model, self).__init__()
1616

1717
def apply_with(self, obj, val, ctx):
18-
""" recursivly apply Schema object
18+
""" recursively apply Schema object
1919
2020
:param obj.Model obj: model object to instruct how to create this model
2121
:param dict val: things used to construct this model

pyswagger/primitives/_str.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def validate_str(obj, ret, val, ctx):
1010
if obj.maxLength and len(ret) > obj.maxLength:
1111
raise ValidationError('[{0}] is longer than {1} characters'.format(ret, str(obj.maxLength)))
1212
if obj.minLength and len(ret) < obj.minLength:
13-
raise ValidationError('[{0}] is shoter than {1} characters'.format(ret, str(obj.minLength)))
13+
raise ValidationError('[{0}] is shorter than {1} characters'.format(ret, str(obj.minLength)))
1414

1515
# TODO: handle pattern
1616
return val

pyswagger/tests/test_utils.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,28 @@ def test_multiple_cycles_2(self):
429429
[2, 3, 5, 4, 2],
430430
[2, 3 ,4, 2]
431431
]))
432+
433+
def test_case_insensitive_dict(self):
434+
""" test utils.CaseInsensitiveDict
435+
"""
436+
normal = utils.CaseInsensitiveDict()
437+
normal['Content-Type'] = 'application/json'
438+
self.assertTrue('Content-Type' in normal)
439+
self.assertTrue('content-type' in normal)
440+
self.assertEqual(normal['content-type'], 'application/json')
441+
442+
# test iteration
443+
for k, v in normal.iteritems():
444+
self.assertEqual(k, 'Content-Type')
445+
self.assertEqual(v, 'application/json')
446+
break
447+
else:
448+
# should not reach here
449+
self.assertTrue(False)
450+
451+
for v in normal.itervalues():
452+
self.assertEqual(v, 'application/json')
453+
break
454+
else:
455+
# should not reach here
456+
self.assertTrue(False)

pyswagger/utils.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import os
1010
import operator
1111
import functools
12+
import collections
1213

1314
#TODO: accept varg
1415
def scope_compose(scope, name, sep=private.SCOPE_SEPARATOR):
@@ -593,3 +594,45 @@ def patch_path(base_path, path):
593594
path = path[1:]
594595

595596
return path
597+
598+
599+
class CaseInsensitiveDict(collections.MutableMapping):
600+
""" a case insensitive dict:
601+
- allow to query with case insensitive keys (get, in)
602+
- iteration would return original key
603+
604+
A reference implementation could be found in
605+
606+
https://github.com/requests/
607+
"""
608+
609+
def __init__(self):
610+
self._store = dict()
611+
612+
def __setitem__(self, key, value):
613+
self._store[key.lower()] = (key, value)
614+
615+
def __getitem__(self, key):
616+
return self._store[key.lower()][1]
617+
618+
def __delitem__(self, key):
619+
del self._store[key.lower()]
620+
621+
def __iter__(self):
622+
return (original_key for original_key, _ in six.itervalues(self._store))
623+
624+
def iteritems(self):
625+
return six.itervalues(self._store)
626+
627+
def itervalues(self):
628+
return (value for _, value in six.itervalues(self._store))
629+
630+
def __in__(self, key):
631+
return key.lower() in self._store
632+
633+
def __len__(self):
634+
return len(self._store)
635+
636+
def __repr__(self):
637+
return str(dict(self.items()))
638+

0 commit comments

Comments
 (0)