Skip to content

Commit 4f285bd

Browse files
committed
Adds required keys report for python
1 parent c9a9ff8 commit 4f285bd

8 files changed

+460
-1
lines changed

analyze_required_keys.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from extracted_key_data_v3specs import required_key_to_qty as required_key_to_qty_module
2+
from language_info import python, mapping_key_language_info
3+
4+
from analyzer import report
5+
6+
7+
def write_python_report(language_info: mapping_key_language_info.MappingKeyLanguagInfo):
8+
general_info = report.TableInfo(
9+
title='Key Information',
10+
table_headers=('Metric', 'Qty'),
11+
table_data=tuple({
12+
'qty_keys': language_info.unique_keys,
13+
'case_insensitieve_collisions_qty': len(language_info.case_insensitieve_collisions),
14+
'invalid_identifiers_qty': len(language_info.invalid_identifiers),
15+
}.items())
16+
)
17+
case_insensitieve_collisions_info = report.TableInfo(
18+
title='Reserved Word Identifiers Info',
19+
table_headers=('Original Key', 'Reserved Word'),
20+
table_data=tuple(language_info.case_insensitieve_collisions.items())
21+
)
22+
invalid_identifiers_info = report.TableInfo(
23+
title='Invalid Identifiers Info',
24+
table_headers=('Original Key', 'Fixed Identifier'),
25+
table_data=tuple(language_info.invalid_identifiers.items())
26+
)
27+
28+
this_report = report.ReportInfo(
29+
title='Required Keyword Naming Info',
30+
description='Checks if mapping required keys are reserved words or would ave invalid getter names',
31+
table_infos={
32+
'general_info': general_info,
33+
'case_insensitieve_collisions_info': case_insensitieve_collisions_info,
34+
'invalid_identifiers_info': invalid_identifiers_info,
35+
}
36+
)
37+
with open('reports/required_keys_python_report.md', 'wt') as stream:
38+
this_report.write(stream)
39+
40+
if __name__ == '__main__':
41+
required_key_to_qty = required_key_to_qty_module.data
42+
qty_key_usages = 0
43+
44+
language_info = mapping_key_language_info.MappingKeyLanguagInfo(
45+
unique_keys=len(required_key_to_qty)
46+
)
47+
for key, usage_qty in required_key_to_qty.items():
48+
qty_key_usages += usage_qty
49+
50+
getter_method = python.get_getter_method(key, language_info)
51+
python.check_identifier(getter_method)
52+
53+
print(language_info)
54+
write_python_report(language_info)

extracted_key_data_v3specs/__init__.py

Whitespace-only changes.

extracted_key_data_v3specs/required_key_to_qty.json

-1
This file was deleted.

extracted_key_data_v3specs/required_key_to_qty.py

+1
Large diffs are not rendered by default.

language_info/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import dataclasses
2+
import typing
3+
4+
@dataclasses.dataclass
5+
class MappingKeyLanguagInfo:
6+
unique_keys: int
7+
case_insensitieve_collisions: typing.Dict[str, str] = dataclasses.field(default_factory=lambda: {})
8+
invalid_identifiers: typing.Dict[str, str] = dataclasses.field(default_factory=lambda: {})

language_info/python.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from . import mapping_key_language_info
2+
3+
reserved_words = {
4+
"property", # decorator
5+
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with", # python reserved words
6+
"assert", "else", "if", "pass", "yield", "break", "except", "import",
7+
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
8+
"return", "def", "for", "lambda", "try", "self", "nonlocal", "None", "True",
9+
"False", "async", "await",
10+
"float", "int", "str", "bool", "dict", "immutabledict", "list", "tuple" # types
11+
}
12+
13+
def get_getter_method(key: str, language_info: mapping_key_language_info.MappingKeyLanguagInfo):
14+
if key.lower() in reserved_words:
15+
print(key)
16+
language_info.case_insensitieve_collisions[key] = key.lower()
17+
18+
updated_key = "get_" + key.lower()
19+
if updated_key.isidentifier():
20+
return updated_key
21+
22+
23+
final_key = ''
24+
for char in updated_key:
25+
if char.isidentifier():
26+
final_key += char
27+
continue
28+
# not valid identifier
29+
if char.isdigit():
30+
final_key += char
31+
continue
32+
final_key += '_'
33+
language_info.invalid_identifiers[key] = final_key
34+
print(f"{key} -> {final_key}")
35+
return final_key
36+
37+
38+
def check_identifier(identifier: str):
39+
if not identifier.isidentifier():
40+
raise ValueError('{!r} is not a valid parameter name'.format(identifier))
41+
42+
43+
"""
44+
Note: the get_ prefx + lower case fixes these colisions
45+
46+
Reserved words that are used:
47+
('self', 609)
48+
('list', 34)
49+
('from', 629)
50+
('Self', 4)
51+
('class', 8)
52+
('continue', 3)
53+
('yield', 2)
54+
('break', 2)
55+
('int', 1)
56+
('From', 11)
57+
('in', 2)
58+
('return', 1)
59+
('global', 2)
60+
('Property', 2)
61+
('property', 4)
62+
('Lambda', 1)
63+
('List', 2)
64+
--------
65+
Python Reserved Work Collision?
66+
17 out of 21,431 required keys
67+
- can be fixed with get_ prefix
68+
69+
Invalid method name in python?
70+
293 out of 21,431 -> 1.3%
71+
"""

0 commit comments

Comments
 (0)