Skip to content

Commit e4fbdfa

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents f00c06e + a4c9ea2 commit e4fbdfa

File tree

7 files changed

+926
-647
lines changed

7 files changed

+926
-647
lines changed

Pipfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ dynamodb_json = "*"
1515
jsonpickle = "*"
1616
jsonref = "*"
1717
jsonschema = "*"
18-
icecream = "*"
1918
pydantic = "*"
2019
pyyaml = "*"
2120
simplejson = "*"

Pipfile.lock

Lines changed: 848 additions & 633 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

acai_aws/apigateway/resolver/modes/directory.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44

55
class DirectoryModeResolver(BaseModeResolver):
66

7+
INIT_FILE = '__init__.py'
8+
79
def __init__(self, **kwargs):
810
super().__init__(**kwargs)
911
self.__handler_path = self.importer.clean_path(kwargs['handlers'])
1012

1113
def _get_file_and_import_path(self, request_path):
14+
# ensure previous lookups don't leave behind path/dynamic state
15+
self.reset()
1216
split_path = self.get_request_path_as_list(request_path)
1317
route_path = self.__get_route_path(split_path)
1418
file_path = self.__handler_path + self.importer.file_separator + route_path
@@ -23,8 +27,12 @@ def __get_route_path(self, split_path):
2327
def __get_import_path_file_tree(self, split_path, split_index, file_tree):
2428
if split_index < len(split_path):
2529
part = split_path[split_index]
26-
possible_directory = part.replace('-', '_')
27-
possible_file = f'{possible_directory}.py'
30+
if part == '':
31+
possible_directory = None
32+
possible_file = self.INIT_FILE
33+
else:
34+
possible_directory = part.replace('-', '_')
35+
possible_file = f'{possible_directory}.py'
2836
if possible_directory in file_tree:
2937
self.__handle_directory_path_part(possible_directory, split_path, split_index, file_tree)
3038
elif possible_file in file_tree:
@@ -40,7 +48,7 @@ def __handle_directory_path_part(self, possible_directory, split_path, split_ind
4048
file_leaf = self.determine_which_file_leaf(file_tree, possible_directory)
4149
self.__get_import_path_file_tree(split_path, split_index+1, file_leaf)
4250
else:
43-
self.append_import_path('__init__.py')
51+
self.append_import_path(self.INIT_FILE)
4452

4553
def __handle_file_path_part(self, possible_file, split_path, split_index, file_tree):
4654
self.append_import_path(possible_file)
@@ -51,7 +59,7 @@ def __handle_dynamic_path_part(self, split_path, split_index, file_tree):
5159
file_part = list(file_tree['__dynamic_files'])[0]
5260
self.append_import_path(file_part)
5361
if '.py' not in file_part and split_index+1 == len(split_path):
54-
self.append_import_path('__init__.py')
62+
self.append_import_path(self.INIT_FILE)
5563
file_leaf = self.determine_which_file_leaf(file_tree, file_part)
5664
self.has_dynamic_route = True
5765
self.dynamic_parts[split_index] = split_path[split_index]

acai_aws/common/logger/common_logger.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import traceback
44

55
import jsonpickle
6-
from icecream import ic
76

87

98
class CommonLogger:
109

1110
def __init__(self):
1211
self.__json = jsonpickle
13-
self.__format = os.getenv('LOG_FORMAT', 'JSON')
12+
env_format = os.getenv('LOG_FORMAT', 'JSON') or 'JSON'
13+
self.__format = env_format.strip().upper()
1414
self.__log_level = os.getenv('LOG_LEVEL', 'INFO')
1515
self.__json.set_encoder_options('simplejson', use_decimal=True)
1616
self.__json.set_preferred_backend('simplejson')
@@ -44,13 +44,17 @@ def __log_json(self, **kwargs):
4444
print(self.__json.encode({
4545
'level': kwargs['level'],
4646
'time': datetime.datetime.now(datetime.timezone.utc).isoformat(),
47-
'error_trace': [trace.strip() for trace in self.__get_traceback().split('\n') if trace],
47+
'trace': [trace.strip() for trace in self.__get_traceback().split('\n') if trace],
4848
'log': kwargs['log']
4949
}, indent=4))
5050

5151
def __log_inline(self, **kwargs):
52-
trace = self.__get_traceback()
53-
prefix = f"{trace}{kwargs['level']}|"
54-
log = kwargs['log']
55-
ic.configureOutput(prefix=prefix, outputFunction=print)
56-
ic(log)
52+
timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
53+
trace = self.__get_traceback().strip().replace('\n', ' | ')
54+
log_value = kwargs['log']
55+
if not isinstance(log_value, str):
56+
log_value = str(log_value)
57+
inline_message = f"{kwargs['level']}|time={timestamp} log={log_value}"
58+
if trace:
59+
inline_message = f"{inline_message} trace={trace}"
60+
print(inline_message)

tests/acai_aws/apigateway/resolver/modes/test_directory.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,25 @@ def test_default_init_get_file_and_import_path(self):
6060
self.assertTrue('tests/mocks/apigateway/resolver/directory_handlers/home/__init__.py' in file_path)
6161
self.assertEqual('tests.mocks.apigateway.resolver.directory_handlers.home.__init__', import_path)
6262

63+
def test_base_path_get_file_and_import_path(self):
64+
base_path_request = mock_request.get_basic()
65+
base_path_request['path'] = self.base_path
66+
request = Request(base_path_request)
67+
file_path, import_path = self.directory_resolver._get_file_and_import_path(request.path)
68+
self.assertTrue('tests/mocks/apigateway/resolver/directory_handlers/__init__.py' in file_path)
69+
self.assertEqual('tests.mocks.apigateway.resolver.directory_handlers.__init__', import_path)
70+
71+
def test_base_path_raises_without_init_file(self):
72+
handler_path = 'tests/mocks/apigateway/resolver/directory_handlers_no_root_init'
73+
base_path_request = mock_request.get_basic()
74+
base_path_request['path'] = self.base_path
75+
request = Request(base_path_request)
76+
directory_resolver = DirectoryModeResolver(base_path=self.base_path, handlers=handler_path)
77+
with self.assertRaises(ApiException) as resolver_error:
78+
directory_resolver._get_file_and_import_path(request.path)
79+
self.assertEqual(resolver_error.exception.code, 404)
80+
self.assertEqual(resolver_error.exception.message, 'route not found')
81+
6382
def test_dynamic_get_file_and_import_path(self):
6483
request = Request(self.dynamic_request)
6584
file_path, import_path = self.directory_resolver._get_file_and_import_path(request.path)
@@ -103,3 +122,9 @@ def test_triple_nested_dynamic_get_file_and_import_path(self):
103122
self.assertTrue('tests/mocks/apigateway/resolver/directory_handlers/user/_user_id/item/_item_id.py' in file_path)
104123
self.assertEqual('tests.mocks.apigateway.resolver.directory_handlers.user._user_id.item._item_id', import_path)
105124

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)

tests/acai_aws/common/test_logger.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import io
2+
import json
13
import os
4+
from contextlib import redirect_stdout
25
from unittest import TestCase, mock
36

47
from acai_aws.common import logger
@@ -54,6 +57,29 @@ def test_logger_logs_error_inline(self):
5457
except Exception as error:
5558
logger.log(level='ERROR', log=error)
5659

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+
5783
@mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local'})
5884
def test_logger_logs_error_as_object(self):
5985
try:
@@ -96,4 +122,3 @@ def test_logger_handles_bad_level(self):
96122
@mock.patch.dict(os.environ, {'RUN_MODE': 'SEE-LOGS', 'LOG_STAGE_VARIABLE': 'STAGE', 'STAGE': 'local', 'LOG_LEVEL': 'ERROR', 'LOG_FORMAT': 'BAD'})
97123
def test_logger_handles_bad_format(self):
98124
logger.log(level='INFO', log={'INFO': 'ignore'})
99-
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def post(request, response):
2+
response.body = {'directory_basic': True}
3+
return response

0 commit comments

Comments
 (0)