py2http 0.1.60__tar.gz → 0.1.62__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {py2http-0.1.60 → py2http-0.1.62}/PKG-INFO +16 -4
  2. {py2http-0.1.60 → py2http-0.1.62}/py2http/__init__.py +6 -6
  3. {py2http-0.1.60 → py2http-0.1.62}/py2http/bottle_plugins.py +18 -19
  4. {py2http-0.1.60 → py2http-0.1.62}/py2http/config.py +20 -19
  5. {py2http-0.1.60 → py2http-0.1.62}/py2http/constants.py +6 -5
  6. {py2http-0.1.60 → py2http-0.1.62}/py2http/decorators.py +131 -75
  7. {py2http-0.1.60 → py2http-0.1.62}/py2http/default_configs.py +38 -38
  8. {py2http-0.1.60 → py2http-0.1.62}/py2http/diagnosis.py +1 -2
  9. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/example_service.py +2 -2
  10. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/example_service_bottle.py +5 -5
  11. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/example_service_flask.py +3 -3
  12. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/object_dispatch.py +13 -10
  13. {py2http-0.1.60 → py2http-0.1.62}/py2http/middleware.py +21 -20
  14. {py2http-0.1.60 → py2http-0.1.62}/py2http/openapi_utils.py +82 -82
  15. {py2http-0.1.60 → py2http-0.1.62}/py2http/route_utils.py +11 -10
  16. {py2http-0.1.60 → py2http-0.1.62}/py2http/schema_tools.py +96 -54
  17. {py2http-0.1.60 → py2http-0.1.62}/py2http/service.py +112 -95
  18. py2http-0.1.62/py2http/tests/example_service_test.py +33 -0
  19. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/simple_run_process_test.py +9 -6
  20. py2http-0.1.62/py2http/tests/test_binary_req.py +114 -0
  21. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/test_decorators.py +9 -9
  22. py2http-0.1.62/py2http/tests/test_not_set_defaults.py +73 -0
  23. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/test_p2h2p.py +14 -15
  24. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/utils_for_testing.py +4 -4
  25. {py2http-0.1.60 → py2http-0.1.62}/py2http/types.py +6 -4
  26. {py2http-0.1.60 → py2http-0.1.62}/py2http/util.py +45 -39
  27. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/PKG-INFO +16 -4
  28. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/SOURCES.txt +2 -0
  29. {py2http-0.1.60 → py2http-0.1.62}/setup.cfg +1 -2
  30. py2http-0.1.60/py2http/tests/example_service_test.py +0 -33
  31. {py2http-0.1.60 → py2http-0.1.62}/LICENSE +0 -0
  32. {py2http-0.1.60 → py2http-0.1.62}/README.md +0 -0
  33. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/__init__.py +0 -0
  34. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/custom_input_mapper.py +0 -0
  35. {py2http-0.1.60 → py2http-0.1.62}/py2http/examples/custom_input_mappers.py +0 -0
  36. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/__init__.py +0 -0
  37. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/objects_for_testing.py +0 -0
  38. {py2http-0.1.60 → py2http-0.1.62}/py2http/tests/test_flask.py +0 -0
  39. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/dependency_links.txt +0 -0
  40. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/not-zip-safe +0 -0
  41. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/requires.txt +0 -0
  42. {py2http-0.1.60 → py2http-0.1.62}/py2http.egg-info/top_level.txt +0 -0
  43. {py2http-0.1.60 → py2http-0.1.62}/setup.py +0 -0
@@ -1,15 +1,27 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: py2http
3
- Version: 0.1.60
3
+ Version: 0.1.62
4
4
  Summary: Declarative HTTP service entry point.
5
5
  Home-page: https://github.com/i2mint/py2http
6
- Author: Otosense
7
6
  License: MIT
8
7
  Keywords: http service,web service
9
8
  Platform: any
10
9
  Description-Content-Type: text/markdown
11
- Provides-Extra: testing
12
10
  License-File: LICENSE
11
+ Requires-Dist: bottle
12
+ Requires-Dist: PyJWT[crypto]
13
+ Requires-Dist: aiohttp
14
+ Requires-Dist: i2
15
+ Requires-Dist: glom
16
+ Requires-Dist: gunicorn
17
+ Requires-Dist: requests
18
+ Requires-Dist: strand
19
+ Requires-Dist: swagger-ui-py
20
+ Requires-Dist: pycparser
21
+ Requires-Dist: http2py
22
+ Provides-Extra: testing
23
+ Requires-Dist: http2py; extra == "testing"
24
+ Dynamic: license-file
13
25
 
14
26
  [Documentation here](https://i2mint.github.io/py2http/)
15
27
 
@@ -1,9 +1,9 @@
1
- """This module provides functionality to easily create HTTP services from Python
2
- functions and class methods. It includes features such as method transformation,
3
- input mapping, output mapping, error handling, and client generation.
4
- The module also allows for customization through various configuration options
5
- and provides the ability to generate OpenAPI specifications for the created HTTP
6
- services. Additionally, it includes middleware, plugins, and decorators to enhance
1
+ """This module provides functionality to easily create HTTP services from Python
2
+ functions and class methods. It includes features such as method transformation,
3
+ input mapping, output mapping, error handling, and client generation.
4
+ The module also allows for customization through various configuration options
5
+ and provides the ability to generate OpenAPI specifications for the created HTTP
6
+ services. Additionally, it includes middleware, plugins, and decorators to enhance
7
7
  the functionality of the HTTP services."""
8
8
 
9
9
  from .middleware import mk_jwt_middleware, mk_superadmin_middleware
@@ -1,5 +1,4 @@
1
- """Plugins for adding middleware functionality to Bottle apps.
2
- """
1
+ """Plugins for adding middleware functionality to Bottle apps."""
3
2
 
4
3
  from bottle import request, response, abort
5
4
  from functools import wraps
@@ -9,7 +8,7 @@ from typing import Iterable
9
8
  from warnings import warn
10
9
  from py2http.constants import JSON_CONTENT_TYPE
11
10
 
12
- OPTIONS = 'OPTIONS'
11
+ OPTIONS = "OPTIONS"
13
12
 
14
13
 
15
14
  class JWTPlugin:
@@ -21,7 +20,7 @@ class JWTPlugin:
21
20
 
22
21
  def __init__(
23
22
  self,
24
- secret: str = '',
23
+ secret: str = "",
25
24
  verify: bool = True,
26
25
  mapper: dict = None,
27
26
  ignore_methods: Iterable[str] = None,
@@ -39,7 +38,7 @@ class JWTPlugin:
39
38
  self._verify = verify
40
39
  self._mapper = mapper if mapper else {}
41
40
  self._ignore_methods = ignore_methods if ignore_methods else []
42
- self._algorithms = algorithms if algorithms else ['HS256']
41
+ self._algorithms = algorithms if algorithms else ["HS256"]
43
42
 
44
43
  def __call__(self, handler):
45
44
  if self._ignore_methods and handler.method_name in self._ignore_methods:
@@ -49,13 +48,13 @@ class JWTPlugin:
49
48
  def wrapped_handler(*args, **kwargs):
50
49
  if request.method == OPTIONS:
51
50
  return handler(*args, *kwargs)
52
- auth_header = request.headers.get('Authorization', '')
51
+ auth_header = request.headers.get("Authorization", "")
53
52
  token = auth_header[7:]
54
53
  try:
55
54
  decoded = jwt.decode(
56
55
  token,
57
56
  self._secret,
58
- options={'verify_signature': self._verify},
57
+ options={"verify_signature": self._verify},
59
58
  algorithms=self._algorithms,
60
59
  )
61
60
  for k, v in self._mapper.items():
@@ -69,10 +68,10 @@ class JWTPlugin:
69
68
  response.content_type = JSON_CONTENT_TYPE
70
69
  return json.dumps(
71
70
  {
72
- 'error': f'Invalid authentication token "{token}", {str(error)}'
71
+ "error": f'Invalid authentication token "{token}", {str(error)}'
73
72
  }
74
73
  )
75
- warn(f'Invalid JWT: {token}')
74
+ warn(f"Invalid JWT: {token}")
76
75
  return handler(*args, **kwargs)
77
76
 
78
77
  return wrapped_handler
@@ -84,12 +83,12 @@ class ApiKeyAuthPlugin:
84
83
 
85
84
  def __call__(self, handler):
86
85
  def wrapped_handler(*args, **kwargs):
87
- auth_header = request.headers.get('Authorization', '')
86
+ auth_header = request.headers.get("Authorization", "")
88
87
  if auth_header == self._api_key:
89
88
  return handler(*args, **kwargs)
90
89
  response.status = 401
91
90
  response.content_type = JSON_CONTENT_TYPE
92
- return json.dumps({'error': 'invalid API key'})
91
+ return json.dumps({"error": "invalid API key"})
93
92
 
94
93
  return wrapped_handler
95
94
 
@@ -97,18 +96,18 @@ class ApiKeyAuthPlugin:
97
96
  # from https://stackoverflow.com/questions/17262170/bottle-py-enabling-cors-for-jquery-ajax-requests
98
97
  # TODO: accept lists of headers and methods as init args
99
98
  class CorsPlugin:
100
- def __init__(self, origins: str = '*'):
99
+ def __init__(self, origins: str = "*"):
101
100
  self._origins = origins
102
101
 
103
102
  def __call__(self, handler):
104
103
  def wrapped_handler(*args, **kwargs):
105
- response.headers['Access-Control-Allow-Origin'] = self._origins
106
- response.headers[
107
- 'Access-Control-Allow-Methods'
108
- ] = 'GET, POST, PUT, DELETE, OPTIONS'
109
- response.headers[
110
- 'Access-Control-Allow-Headers'
111
- ] = 'Origin, Accept, Content-Type, X-Requested-With, Authorization, X-api-key'
104
+ response.headers["Access-Control-Allow-Origin"] = self._origins
105
+ response.headers["Access-Control-Allow-Methods"] = (
106
+ "GET, POST, PUT, DELETE, OPTIONS"
107
+ )
108
+ response.headers["Access-Control-Allow-Headers"] = (
109
+ "Origin, Accept, Content-Type, X-Requested-With, Authorization, X-api-key"
110
+ )
112
111
  if request.method != OPTIONS:
113
112
  return handler(*args, **kwargs)
114
113
 
@@ -1,22 +1,23 @@
1
- """The code module provides functions for retrieving configuration values for a
2
- function based on a hierarchy of sources, including function properties,
3
- configuration dictionaries, and default values. The `get_result` function is used to
4
- allow nested configurations by function name, with an example provided in the docstring
5
- for illustration.
1
+ """The code module provides functions for retrieving configuration values for a
2
+ function based on a hierarchy of sources, including function properties,
3
+ configuration dictionaries, and default values. The `get_result` function is used to
4
+ allow nested configurations by function name, with an example provided in the docstring
5
+ for illustration.
6
6
 
7
- The `mk_config` function is used to get a configuration value for a function by checking
8
- the function properties, configuration dictionaries, and default values. It also allows
9
- for specifying the expected type of the output, with options to provide additional
10
- options such as the function name and expected type.
7
+ The `mk_config` function is used to get a configuration value for a function by checking
8
+ the function properties, configuration dictionaries, and default values. It also allows
9
+ for specifying the expected type of the output, with options to provide additional
10
+ options such as the function name and expected type.
11
11
 
12
- Overall, the module helps manage and retrieve configuration values for functions,
12
+ Overall, the module helps manage and retrieve configuration values for functions,
13
13
  ensuring they are appropriately set and validated based on the function's requirements.
14
14
  """
15
+
15
16
  from typing import Callable
16
17
 
17
- AIOHTTP = 'aiohttp'
18
- BOTTLE = 'bottle'
19
- FLASK = 'flask'
18
+ AIOHTTP = "aiohttp"
19
+ BOTTLE = "bottle"
20
+ FLASK = "flask"
20
21
 
21
22
 
22
23
  def get_result(configs, func, funcname, key, options):
@@ -41,9 +42,9 @@ def get_result(configs, func, funcname, key, options):
41
42
  dict_value = result.get(funcname, None)
42
43
  if dict_value:
43
44
  result = dict_value
44
- elif '$else' in result:
45
- result = result['$else']
46
- elif options.get('type', None) is not dict:
45
+ elif "$else" in result:
46
+ result = result["$else"]
47
+ elif options.get("type", None) is not dict:
47
48
  result = None
48
49
  return result
49
50
 
@@ -66,12 +67,12 @@ def mk_config(key, func, configs, defaults, **options):
66
67
  * *type*
67
68
  The expected type of the output (use Callable for functions)
68
69
  """
69
- funcname = options.get('funcname', getattr(func, '__name__', None))
70
+ funcname = options.get("funcname", getattr(func, "__name__", None))
70
71
 
71
72
  result = get_result(configs, func, funcname, key, options)
72
73
 
73
74
  if result:
74
- expected_type = options.get('type', None) # align names expected_type <-> type
75
+ expected_type = options.get("type", None) # align names expected_type <-> type
75
76
  if not expected_type:
76
77
  assert key in defaults, f'Missing default value for key "{key}"'
77
78
  default_value = defaults.get(key)
@@ -81,7 +82,7 @@ def mk_config(key, func, configs, defaults, **options):
81
82
  expected_type = type(default_value)
82
83
  assert expected_type == type(None) or isinstance(
83
84
  result, expected_type
84
- ), f'Config {key} does not match type {expected_type}.'
85
+ ), f"Config {key} does not match type {expected_type}."
85
86
  else:
86
87
  result = defaults.get(key, None)
87
88
  return result
@@ -1,6 +1,7 @@
1
1
  """This module provides functionality for dispatching Python functions as HTTP services. It allows users to create a basic HTTP server from a list of functions or instance methods, customize input and output mapping, handle errors, generate client code from an OpenAPI specification, and configure various aspects of the server setup. The module includes features for transforming class methods, mapping input and output data, handling errors, and generating client code. It also supports configuration options for the HTTP framework, input and output mappers, error handlers, openAPI specifications, logging, middleware, plugins, CORS, SSL certificates, and more."""
2
- JSON_CONTENT_TYPE = 'application/json'
3
- BINARY_CONTENT_TYPE = 'application/octet-stream'
4
- FORM_CONTENT_TYPE = 'multipart/form-data'
5
- RAW_CONTENT_TYPE = 'text/plain'
6
- HTML_CONTENT_TYPE = 'text/html'
2
+
3
+ JSON_CONTENT_TYPE = "application/json"
4
+ BINARY_CONTENT_TYPE = "application/octet-stream"
5
+ FORM_CONTENT_TYPE = "multipart/form-data"
6
+ RAW_CONTENT_TYPE = "text/plain"
7
+ HTML_CONTENT_TYPE = "text/html"