acai-aws 2.2.7__py3-none-any.whl → 2.2.9__py3-none-any.whl

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.
@@ -4,11 +4,15 @@ from acai_aws.apigateway.exception import ApiException
4
4
 
5
5
  class DirectoryModeResolver(BaseModeResolver):
6
6
 
7
+ INIT_FILE = '__init__.py'
8
+
7
9
  def __init__(self, **kwargs):
8
10
  super().__init__(**kwargs)
9
11
  self.__handler_path = self.importer.clean_path(kwargs['handlers'])
10
12
 
11
13
  def _get_file_and_import_path(self, request_path):
14
+ # ensure previous lookups don't leave behind path/dynamic state
15
+ self.reset()
12
16
  split_path = self.get_request_path_as_list(request_path)
13
17
  route_path = self.__get_route_path(split_path)
14
18
  file_path = self.__handler_path + self.importer.file_separator + route_path
@@ -25,7 +29,7 @@ class DirectoryModeResolver(BaseModeResolver):
25
29
  part = split_path[split_index]
26
30
  if part == '':
27
31
  possible_directory = None
28
- possible_file = '__init__.py'
32
+ possible_file = self.INIT_FILE
29
33
  else:
30
34
  possible_directory = part.replace('-', '_')
31
35
  possible_file = f'{possible_directory}.py'
@@ -44,7 +48,7 @@ class DirectoryModeResolver(BaseModeResolver):
44
48
  file_leaf = self.determine_which_file_leaf(file_tree, possible_directory)
45
49
  self.__get_import_path_file_tree(split_path, split_index+1, file_leaf)
46
50
  else:
47
- self.append_import_path('__init__.py')
51
+ self.append_import_path(self.INIT_FILE)
48
52
 
49
53
  def __handle_file_path_part(self, possible_file, split_path, split_index, file_tree):
50
54
  self.append_import_path(possible_file)
@@ -55,7 +59,7 @@ class DirectoryModeResolver(BaseModeResolver):
55
59
  file_part = list(file_tree['__dynamic_files'])[0]
56
60
  self.append_import_path(file_part)
57
61
  if '.py' not in file_part and split_index+1 == len(split_path):
58
- self.append_import_path('__init__.py')
62
+ self.append_import_path(self.INIT_FILE)
59
63
  file_leaf = self.determine_which_file_leaf(file_tree, file_part)
60
64
  self.has_dynamic_route = True
61
65
  self.dynamic_parts[split_index] = split_path[split_index]
@@ -10,7 +10,8 @@ class CommonLogger:
10
10
 
11
11
  def __init__(self):
12
12
  self.__json = jsonpickle
13
- self.__format = os.getenv('LOG_FORMAT', 'JSON')
13
+ env_format = os.getenv('LOG_FORMAT', 'JSON') or 'JSON'
14
+ self.__format = env_format.strip().upper()
14
15
  self.__log_level = os.getenv('LOG_LEVEL', 'INFO')
15
16
  self.__json.set_encoder_options('simplejson', use_decimal=True)
16
17
  self.__json.set_preferred_backend('simplejson')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acai_aws
3
- Version: 2.2.7
3
+ Version: 2.2.9
4
4
  Summary: DRY, configurable, declarative framework for building AWS Lambda APIs and event processors
5
5
  Home-page: https://github.com/syngenta/acai-python
6
6
  Author: Paul Cruse III
@@ -13,7 +13,7 @@ acai_aws/apigateway/resolver/cache.py,sha256=myABSHkAx7ZEsW8_NWCGccnICJ9PXmY43GH
13
13
  acai_aws/apigateway/resolver/importer.py,sha256=h4EKqECW35UfDXJjKxD2ClLvDN8lXl0oiWSqsWAgqAU,3757
14
14
  acai_aws/apigateway/resolver/modes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  acai_aws/apigateway/resolver/modes/base.py,sha256=ZXhRHKsfltuZZAfoRyJ8fZXnliGHQxncB5kryuWnLNY,1760
16
- acai_aws/apigateway/resolver/modes/directory.py,sha256=zr2U0_LD7ImBa0dOnHcwJyt19wwVDreoCwx7-3nwi60,3167
16
+ acai_aws/apigateway/resolver/modes/directory.py,sha256=2r0HK020ingbtLnjKm955WTNVJp9j6rbTnIVQegLPv4,3294
17
17
  acai_aws/apigateway/resolver/modes/mapping.py,sha256=B699anOGoX2XfwYAjIaYQ8FM83eSi0z0lYHTO_bdIsM,3099
18
18
  acai_aws/apigateway/resolver/modes/pattern.py,sha256=SWb8713ohEI216RKK6lvAUuleiW161293GUCrr7gSVk,2701
19
19
  acai_aws/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -26,7 +26,7 @@ acai_aws/common/json_helper.py,sha256=HoCaF0fO_EXcVbwanZ9Cg66x9oQUQyXbEdLfResFpq
26
26
  acai_aws/common/schema.py,sha256=mbtD922dsNzZX2uZjJKXFVj9IShpgBRofTVmdNyLGyE,3549
27
27
  acai_aws/common/validator.py,sha256=uYFMPGM5dvsiKxuwFGxetwqGcRNm03BZ3YJ6lNedwck,6575
28
28
  acai_aws/common/logger/__init__.py,sha256=2ItzGhXLdTwt9tKAOa5dzgQlLouJKQbUhV4qjxBLl1g,241
29
- acai_aws/common/logger/common_logger.py,sha256=bcOs1HRhqLHOp5P6tZQ821tqfSa7x_oBHrlY5o0lCWk,1977
29
+ acai_aws/common/logger/common_logger.py,sha256=WxhSvsC2a2DZYuWatpdOPraromrIUItZw1boP10kw5U,2035
30
30
  acai_aws/common/logger/decorator.py,sha256=Nf7S--7mWKVkKiRB2fVNM9B4NBFpJeTGv0FYxK0DEvU,749
31
31
  acai_aws/common/records/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  acai_aws/common/records/event.py,sha256=F6fqxSRWfAbEH8n_Vw9ZQICcNd__rWRGpMv1T0deQ8o,621
@@ -72,7 +72,7 @@ acai_aws/sqs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  acai_aws/sqs/event.py,sha256=u5QYrb-XLy2mhzi3v55je6N6vASS3ywzjIBDjm_n32Q,264
73
73
  acai_aws/sqs/record.py,sha256=b-9gidW2UvuSZU00sgZV90DuUj7r12zTXYbQLNBSYjk,1909
74
74
  acai_aws/sqs/requirements.py,sha256=4QR0LIrDqF1CPSAroscX3EAys-dbqWMFmOhqyILcViw,116
75
- acai_aws-2.2.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
75
+ acai_aws-2.2.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
76
76
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
77
  tests/acai_aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  tests/acai_aws/apigateway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -97,7 +97,7 @@ tests/acai_aws/apigateway/resolver/test_cacher.py,sha256=NSPMdy9IIapEz6BSOppKpKD
97
97
  tests/acai_aws/apigateway/resolver/test_importer.py,sha256=9gb8cv8gPeWap5eIb8S5zp6fl1ZebKRCriAueR0f1A0,4685
98
98
  tests/acai_aws/apigateway/resolver/test_init.py,sha256=6c0ok7924i2EaynfLOx_7W-h-RgNAKiur63-NZQ3JUk,3277
99
99
  tests/acai_aws/apigateway/resolver/modes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
- tests/acai_aws/apigateway/resolver/modes/test_directory.py,sha256=ghsHW7cD-Tniw438GXUbF6xey5Ntr3QuZUmWQVj5eDs,7069
100
+ tests/acai_aws/apigateway/resolver/modes/test_directory.py,sha256=o2LIFI-bYP0qGF5Q5Dfzc_EG1pkHn4VHgWGEk_v8eqs,7525
101
101
  tests/acai_aws/apigateway/resolver/modes/test_mapping.py,sha256=j_nMWfO6KqRSt2sGkVNIQQKOzNNvXvp-hfNPX-ESnOc,6532
102
102
  tests/acai_aws/apigateway/resolver/modes/test_pattern.py,sha256=CEqPVlCNniVU5N9y4WKYhEqI_gLwpswbRdBZYPZmd2E,6020
103
103
  tests/acai_aws/apigateway/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -107,7 +107,7 @@ tests/acai_aws/apigateway/router/test_pattern_router.py,sha256=981DrtlSSfaWSiDMQ
107
107
  tests/acai_aws/apigateway/router/test_timeout.py,sha256=Jv5Bk3s91kL4lBQAxxQ3NzjLnpKbeg845w4GpLwLkZA,2546
108
108
  tests/acai_aws/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  tests/acai_aws/common/test_json_helper.py,sha256=P7kw_KIaVQFr9JQAFHd4jdbvg1uVQ5l5pQmx8HmFg88,1389
110
- tests/acai_aws/common/test_logger.py,sha256=LFpZyDSoibg_rl82PMRn83uf7CvR0slH7g9wK7gaKeQ,4639
110
+ tests/acai_aws/common/test_logger.py,sha256=Aq4o43embLWofq9gG-JCY4nH4ohIqjdkwAU9nsrqkDE,5906
111
111
  tests/acai_aws/common/test_schema.py,sha256=WbSBwYGrdraF3EtuDB9XWYREKk_W14317jrTXEo90xY,5658
112
112
  tests/acai_aws/common/test_validator.py,sha256=9hDpf-UGCrQ1Elx0Th8wezLQ0HkUoKj-UXuLDGT5GJU,5958
113
113
  tests/acai_aws/common/records/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -154,7 +154,7 @@ tests/acai_aws/sqs/test_event.py,sha256=d8JBttuLND_qBVdLAoqtp-_qJ5NXxD6Ai2IFmUqK
154
154
  tests/acai_aws/sqs/test_record.py,sha256=RkWpc24A-f4bw1VyMM5mEp97QCk4i-Weu6CFP0-VlbU,1602
155
155
  tests/acai_aws/sqs/test_requirements.py,sha256=wcV99aXQIL8t6gIeUO0EgX9c_hA0IV3rg2Ar1g1SYjg,904
156
156
  tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
- acai_aws-2.2.7.dist-info/METADATA,sha256=JMEq-FrEyr-K-n_IrO4Pt1ufyGGATNDt06jeWsTbtos,15175
158
- acai_aws-2.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
159
- acai_aws-2.2.7.dist-info/top_level.txt,sha256=A6vdhfU7MqNqO9rGdH1Z2EEqpnbIIyb4PsHJbRktbbI,15
160
- acai_aws-2.2.7.dist-info/RECORD,,
157
+ acai_aws-2.2.9.dist-info/METADATA,sha256=ImieSh-sZSiYEMoNPsc46pDgm85xGuMaGftqgd62OqU,15175
158
+ acai_aws-2.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
159
+ acai_aws-2.2.9.dist-info/top_level.txt,sha256=A6vdhfU7MqNqO9rGdH1Z2EEqpnbIIyb4PsHJbRktbbI,15
160
+ acai_aws-2.2.9.dist-info/RECORD,,
@@ -121,3 +121,10 @@ class DirectoryModeResolverTest(unittest.TestCase):
121
121
  file_path, import_path = self.directory_resolver._get_file_and_import_path(request.path)
122
122
  self.assertTrue('tests/mocks/apigateway/resolver/directory_handlers/user/_user_id/item/_item_id.py' in file_path)
123
123
  self.assertEqual('tests.mocks.apigateway.resolver.directory_handlers.user._user_id.item._item_id', import_path)
124
+
125
+ def test_repeated_directory_request_resets_import_path(self):
126
+ request = Request(self.init_request)
127
+ first_file_path, first_import_path = self.directory_resolver._get_file_and_import_path(request.path)
128
+ second_file_path, second_import_path = self.directory_resolver._get_file_and_import_path(request.path)
129
+ self.assertEqual(first_file_path, second_file_path)
130
+ self.assertEqual(first_import_path, second_import_path)
@@ -1,4 +1,7 @@
1
+ import io
2
+ import json
1
3
  import os
4
+ from contextlib import redirect_stdout
2
5
  from unittest import TestCase, mock
3
6
 
4
7
  from acai_aws.common import logger
@@ -54,6 +57,29 @@ class LoggerTest(TestCase):
54
57
  except Exception as error:
55
58
  logger.log(level='ERROR', log=error)
56
59
 
60
+ @mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local', 'LOG_FORMAT': ' inline '})
61
+ def test_logger_logs_error_inline_with_messy_env(self):
62
+ logger.log(level='INFO', log={'message': 'inline-format'})
63
+
64
+ @mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local', 'LOG_FORMAT': 'JSON'})
65
+ def test_logger_json_output(self):
66
+ buffer = io.StringIO()
67
+ with redirect_stdout(buffer):
68
+ logger.log(level='WARN', log={'json': True})
69
+ log_output = buffer.getvalue().strip()
70
+ parsed = json.loads(log_output)
71
+ self.assertEqual('WARN', parsed['level'])
72
+ self.assertEqual({'json': True}, parsed['log'])
73
+
74
+ @mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local', 'LOG_FORMAT': 'INLINE'})
75
+ def test_logger_inline_output(self):
76
+ buffer = io.StringIO()
77
+ with redirect_stdout(buffer):
78
+ logger.log(level='INFO', log={'inline': True})
79
+ log_output = buffer.getvalue().strip()
80
+ self.assertTrue(log_output.startswith('INFO|'))
81
+ self.assertIn("inline': True", log_output)
82
+
57
83
  @mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local'})
58
84
  def test_logger_logs_error_as_object(self):
59
85
  try:
@@ -96,4 +122,3 @@ class LoggerTest(TestCase):
96
122
  @mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local', 'LOG_LEVEL': 'ERROR', 'LOG_FORMAT': 'BAD'})
97
123
  def test_logger_handles_bad_format(self):
98
124
  logger.log(level='INFO', log={'INFO': 'ignore'})
99
-