From 747ab07a557fd3391bec08d8abc579646dc57c1f Mon Sep 17 00:00:00 2001 From: Md Safiyat Reza Date: Sat, 10 Jul 2021 02:09:59 +0530 Subject: [PATCH 1/6] Added a custom JSON encoder for json.dumps(). Added a custom JSON encoder based on json.JSONEncoder. Changes from the default behaviour: - Using `_make_iterencode` as the only `_iterencode`. - Change `_make_iterencode`, setting `_indent` in `_iterencode_dict` to `None`. - Use `py_encode_basestring` as the only `encoder`. Also, updated the json writer to sort keys according to requested top_keys. Signed-off-by: Md Safiyat Reza --- pre_commit_hooks/pretty_format_json.py | 239 +++++++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/pre_commit_hooks/pretty_format_json.py b/pre_commit_hooks/pretty_format_json.py index 61b01698..3f8d65e6 100644 --- a/pre_commit_hooks/pretty_format_json.py +++ b/pre_commit_hooks/pretty_format_json.py @@ -9,6 +9,243 @@ from typing import Tuple from typing import Union +INFINITY = float('inf') + + +def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, + _key_separator, _item_separator, _sort_keys, _skipkeys, + _one_shot, + ## HACK: hand-optimized bytecode; turn globals into locals + ValueError=ValueError, + dict=dict, + float=float, + id=id, + int=int, + isinstance=isinstance, + list=list, + str=str, + tuple=tuple, + _intstr=int.__str__, + ): + + if _indent is not None and not isinstance(_indent, str): + _indent = ' ' * _indent + + def _iterencode_list(lst, _current_indent_level): + if not lst: + yield '[]' + return + if markers is not None: + markerid = id(lst) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = lst + buf = '[' + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + _indent * _current_indent_level + separator = _item_separator.rstrip() + newline_indent + buf += newline_indent + else: + newline_indent = None + separator = _item_separator + first = True + for value in lst: + if first: + first = False + else: + buf = separator + if isinstance(value, str): + yield buf + _encoder(value) + elif value is None: + yield buf + 'null' + elif value is True: + yield buf + 'true' + elif value is False: + yield buf + 'false' + elif isinstance(value, int): + # Subclasses of int/float may override __str__, but we still + # want to encode them as integers/floats in JSON. One example + # within the standard library is IntEnum. + yield buf + _intstr(value) + elif isinstance(value, float): + # see comment above for int + yield buf + _floatstr(value) + else: + yield buf + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + yield from chunks + if newline_indent is not None: + _current_indent_level -= 1 + yield '\n' + _indent * _current_indent_level + yield ']' + if markers is not None: + del markers[markerid] + + def _iterencode_dict(dct, _current_indent_level): + if not dct: + yield '{}' + return + _indent = None # No newlines or indentation for the k-v pairs. + if markers is not None: + markerid = id(dct) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = dct + yield '{' + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + _indent * _current_indent_level + item_separator = _item_separator + newline_indent + yield newline_indent + else: + newline_indent = None + item_separator = _item_separator + first = True + if _sort_keys: + items = sorted(dct.items(), key=lambda kv: kv[0]) + else: + items = dct.items() + for key, value in items: + if isinstance(key, str): + pass + # JavaScript is weakly typed for these, so it makes sense to + # also allow them. Many encoders seem to do something like this. + elif isinstance(key, float): + # see comment for int/float in _make_iterencode + key = _floatstr(key) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, int): + # see comment for int/float in _make_iterencode + key = _intstr(key) + elif _skipkeys: + continue + else: + raise TypeError(f'keys must be str, int, float, bool or None, ' + f'not {key.__class__.__name__}') + if first: + first = False + else: + yield item_separator + yield _encoder(key) + yield _key_separator + if isinstance(value, str): + yield _encoder(value) + elif value is None: + yield 'null' + elif value is True: + yield 'true' + elif value is False: + yield 'false' + elif isinstance(value, int): + # see comment for int/float in _make_iterencode + yield _intstr(value) + elif isinstance(value, float): + # see comment for int/float in _make_iterencode + yield _floatstr(value) + else: + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + yield from chunks + if newline_indent is not None: + _current_indent_level -= 1 + yield '\n' + _indent * _current_indent_level + yield '}' + if markers is not None: + del markers[markerid] + + def _iterencode(o, _current_indent_level): + if isinstance(o, str): + yield _encoder(o) + elif o is None: + yield 'null' + elif o is True: + yield 'true' + elif o is False: + yield 'false' + elif isinstance(o, int): + # see comment for int/float in _make_iterencode + yield _intstr(o) + elif isinstance(o, float): + # see comment for int/float in _make_iterencode + yield _floatstr(o) + elif isinstance(o, (list, tuple)): + yield from _iterencode_list(o, _current_indent_level) + elif isinstance(o, dict): + yield from _iterencode_dict(o, _current_indent_level) + else: + if markers is not None: + markerid = id(o) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = o + o = _default(o) + yield from _iterencode(o, _current_indent_level) + if markers is not None: + del markers[markerid] + return _iterencode + + +class CustomJSONEncoder(json.JSONEncoder): + def iterencode(self, o, _one_shot=False): + """Encode the given object and yield each string + representation as available. + + For example:: + + for chunk in JSONEncoder().iterencode(bigobject): + mysocket.write(chunk) + + """ + if self.check_circular: + markers = {} + else: + markers = None + + def floatstr(o, allow_nan=self.allow_nan, + _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY): + # Check for specials. Note that this type of test is processor + # and/or platform-specific, so do tests which don't depend on the + # internals. + + if o != o: + text = 'NaN' + elif o == _inf: + text = 'Infinity' + elif o == _neginf: + text = '-Infinity' + else: + return _repr(o) + + if not allow_nan: + raise ValueError( + "Out of range float values are not JSON compliant: " + + repr(o)) + + return text + + _encoder = json.encoder.py_encode_basestring + + _iterencode = _make_iterencode( + markers, self.default, _encoder, self.indent, floatstr, + self.key_separator, self.item_separator, self.sort_keys, + self.skipkeys, _one_shot) + return _iterencode(o, 0) + def _get_pretty_format( contents: str, @@ -28,6 +265,8 @@ def pairs_first(pairs: Sequence[Tuple[str, str]]) -> Mapping[str, str]: json.loads(contents, object_pairs_hook=pairs_first), indent=indent, ensure_ascii=ensure_ascii, + cls=CustomJSONEncoder, + separators=(', ', ': ') ) return f'{json_pretty}\n' From 2331edcb1d8395be3d112f0eba6dc48b0a90f1b0 Mon Sep 17 00:00:00 2001 From: Tanmay Pandey Date: Thu, 15 Sep 2022 11:25:52 +0530 Subject: [PATCH 2/6] [Delivers #183229025] Add duplicate entry and sort feature for json Signed-off-by: Tanmay Pandey --- .pre-commit-hooks.yaml | 5 ++ pre_commit_hooks/notify_duplicate_entry.py | 59 +++++++++++++++++ pre_commit_hooks/pretty_format_json.py | 74 ++++++++++++++-------- setup.cfg | 1 + 4 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 pre_commit_hooks/notify_duplicate_entry.py diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 91dbdf0b..640c1733 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -191,3 +191,8 @@ language: python types: [text] stages: [commit, push, manual] +- id: notify-duplicate-entry + name: Notify duplicate entry + description: Notifies duplicate entry in the same file + entry: notify-duplicate-entry + language: python diff --git a/pre_commit_hooks/notify_duplicate_entry.py b/pre_commit_hooks/notify_duplicate_entry.py new file mode 100644 index 00000000..347d1c2e --- /dev/null +++ b/pre_commit_hooks/notify_duplicate_entry.py @@ -0,0 +1,59 @@ +import argparse +import json +from typing import Optional +from typing import Sequence +from pathlib import Path + +def _check_duplicate_entry(json_contents, key): + json_dict = {} + duplicate_uuids = set() + for row in json_contents: + if row[key] not in json_dict: + json_dict[row[key]] = row + else: + duplicate_uuids.add(row[key]) + return duplicate_uuids, len(duplicate_uuids) + + +def main(argv: Optional[Sequence[str]] = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('filenames', nargs='*', type=str, + help='Names of the JSON files to check duplicate entries' + ) + table_uuid_mapping = { + 'action': 'uuid', 'env_property_group': 'uuid', + 'environment': 'uuid', 'environment_property': 'code', + 'report_summary': 'uuid', + 'runner': 'uuid', 'scenario': 'uuid', + 'sla': 'uuid', 'sla_scenario_association': 'sla', 'tag': 'uuid', + 'tag_action_association': 'tag_uuid', + 'tag_case_association': 'test_case_uuid', + 'teams': 'uuid', + 'test_case': 'uuid', + 'test_suit': 'uuid', 'test_supported_version': 'test_case_uuid', + 'testcase_workload_association': 'uuid', 'user': 'uuid', + 'user_tokens': 'user_token', 'workflow_task': 'workflow_id' + } + + args = vars(parser.parse_args(argv)) + filenames = args['filenames'] + flag = False + + for i in range(len(filenames)): + json_file = filenames[i] + file_name = Path(filenames[i]).stem + key = table_uuid_mapping[file_name] + with open(json_file, encoding='UTF-8') as f: + contents = json.load(f) + duplicate_uuids, status = _check_duplicate_entry(contents, key) + + if status: + print(f"Duplicate UUIDs found - {duplicate_uuids} in file " + f"{json_file}") + flag = True + + return flag + + +if __name__ == "__main__": + exit(main()) diff --git a/pre_commit_hooks/pretty_format_json.py b/pre_commit_hooks/pretty_format_json.py index 3f8d65e6..238dc10f 100644 --- a/pre_commit_hooks/pretty_format_json.py +++ b/pre_commit_hooks/pretty_format_json.py @@ -12,21 +12,22 @@ INFINITY = float('inf') -def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, - _key_separator, _item_separator, _sort_keys, _skipkeys, - _one_shot, - ## HACK: hand-optimized bytecode; turn globals into locals - ValueError=ValueError, - dict=dict, - float=float, - id=id, - int=int, - isinstance=isinstance, - list=list, - str=str, - tuple=tuple, - _intstr=int.__str__, - ): +def _make_iterencode( + markers, _default, _encoder, _indent, _floatstr, + _key_separator, _item_separator, _sort_keys, _skipkeys, + _one_shot, + ## HACK: hand-optimized bytecode; turn globals into locals + ValueError=ValueError, + dict=dict, + float=float, + id=id, + int=int, + isinstance=isinstance, + list=list, + str=str, + tuple=tuple, + _intstr=int.__str__, +): if _indent is not None and not isinstance(_indent, str): _indent = ' ' * _indent @@ -38,7 +39,7 @@ def _iterencode_list(lst, _current_indent_level): if markers is not None: markerid = id(lst) if markerid in markers: - raise ValueError("Circular reference detected") + raise ValueError('Circular reference detected') markers[markerid] = lst buf = '[' if _indent is not None: @@ -95,7 +96,7 @@ def _iterencode_dict(dct, _current_indent_level): if markers is not None: markerid = id(dct) if markerid in markers: - raise ValueError("Circular reference detected") + raise ValueError('Circular reference detected') markers[markerid] = dct yield '{' if _indent is not None: @@ -131,8 +132,10 @@ def _iterencode_dict(dct, _current_indent_level): elif _skipkeys: continue else: - raise TypeError(f'keys must be str, int, float, bool or None, ' - f'not {key.__class__.__name__}') + raise TypeError( + f'keys must be str, int, float, bool or None, ' + f'not {key.__class__.__name__}', + ) if first: first = False else: @@ -191,7 +194,7 @@ def _iterencode(o, _current_indent_level): if markers is not None: markerid = id(o) if markerid in markers: - raise ValueError("Circular reference detected") + raise ValueError('Circular reference detected') markers[markerid] = o o = _default(o) yield from _iterencode(o, _current_indent_level) @@ -216,8 +219,10 @@ def iterencode(self, o, _one_shot=False): else: markers = None - def floatstr(o, allow_nan=self.allow_nan, - _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY): + def floatstr( + o, allow_nan=self.allow_nan, + _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY, + ): # Check for specials. Note that this type of test is processor # and/or platform-specific, so do tests which don't depend on the # internals. @@ -233,8 +238,9 @@ def floatstr(o, allow_nan=self.allow_nan, if not allow_nan: raise ValueError( - "Out of range float values are not JSON compliant: " + - repr(o)) + 'Out of range float values are not JSON compliant: ' + + repr(o), + ) return text @@ -243,7 +249,8 @@ def floatstr(o, allow_nan=self.allow_nan, _iterencode = _make_iterencode( markers, self.default, _encoder, self.indent, floatstr, self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, _one_shot) + self.skipkeys, _one_shot, + ) return _iterencode(o, 0) @@ -253,6 +260,7 @@ def _get_pretty_format( ensure_ascii: bool = True, sort_keys: bool = True, top_keys: Sequence[str] = (), + sort_by_first_key: bool = False, ) -> str: def pairs_first(pairs: Sequence[Tuple[str, str]]) -> Mapping[str, str]: before = [pair for pair in pairs if pair[0] in top_keys] @@ -261,12 +269,16 @@ def pairs_first(pairs: Sequence[Tuple[str, str]]) -> Mapping[str, str]: if sort_keys: after.sort() return dict(before + after) + + json_contents = json.loads(contents, object_pairs_hook=pairs_first) + if sort_by_first_key: + json_contents.sort(key=lambda row: list(row.values())[0]) json_pretty = json.dumps( - json.loads(contents, object_pairs_hook=pairs_first), + json_contents, indent=indent, ensure_ascii=ensure_ascii, cls=CustomJSONEncoder, - separators=(', ', ': ') + separators=(', ', ': '), ) return f'{json_pretty}\n' @@ -337,6 +349,13 @@ def main(argv: Optional[Sequence[str]] = None) -> int: default=[], help='Ordered list of keys to keep at the top of JSON hashes', ) + parser.add_argument( + '--sort-by-first-key', + dest='sort_by_first_key', + action='store_true', + default=False, + help='Sort the json by a specific key', + ) parser.add_argument('filenames', nargs='*', help='Filenames to fix') args = parser.parse_args(argv) @@ -350,6 +369,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int: pretty_contents = _get_pretty_format( contents, args.indent, ensure_ascii=not args.no_ensure_ascii, sort_keys=not args.no_sort_keys, top_keys=args.top_keys, + sort_by_first_key=args.sort_by_first_key, ) except ValueError: print( diff --git a/setup.cfg b/setup.cfg index a5ad401a..b46ffac0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -61,6 +61,7 @@ console_scripts = forbid-new-submodules = pre_commit_hooks.forbid_new_submodules:main mixed-line-ending = pre_commit_hooks.mixed_line_ending:main name-tests-test = pre_commit_hooks.tests_should_end_in_test:main + notify-duplicate-entry = pre_commit_hooks.notify_duplicate_entry:main no-commit-to-branch = pre_commit_hooks.no_commit_to_branch:main pre-commit-hooks-removed = pre_commit_hooks.removed:main pretty-format-json = pre_commit_hooks.pretty_format_json:main From 024ded4078e9470d703dfd9c97614710832d5179 Mon Sep 17 00:00:00 2001 From: Tanmay Pandey Date: Wed, 12 Apr 2023 21:36:38 +0530 Subject: [PATCH 3/6] VOER-75 Add context table --- pre_commit_hooks/notify_duplicate_entry.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pre_commit_hooks/notify_duplicate_entry.py b/pre_commit_hooks/notify_duplicate_entry.py index 347d1c2e..e323e2e2 100644 --- a/pre_commit_hooks/notify_duplicate_entry.py +++ b/pre_commit_hooks/notify_duplicate_entry.py @@ -32,7 +32,8 @@ def main(argv: Optional[Sequence[str]] = None) -> int: 'test_case': 'uuid', 'test_suit': 'uuid', 'test_supported_version': 'test_case_uuid', 'testcase_workload_association': 'uuid', 'user': 'uuid', - 'user_tokens': 'user_token', 'workflow_task': 'workflow_id' + 'user_tokens': 'user_token', 'workflow_task': 'workflow_id', + 'context': 'uuid', } args = vars(parser.parse_args(argv)) From ee7cee9a8b1a309d63ce8de76df53056616d6c00 Mon Sep 17 00:00:00 2001 From: Deepanshu Bhatia Date: Thu, 27 Apr 2023 07:08:15 +0530 Subject: [PATCH 4/6] EIR-11: Fix duplicate entry checker for composite primary keys --- pre_commit_hooks/notify_duplicate_entry.py | 66 ++++++++++++++-------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/pre_commit_hooks/notify_duplicate_entry.py b/pre_commit_hooks/notify_duplicate_entry.py index e323e2e2..7f277f4c 100644 --- a/pre_commit_hooks/notify_duplicate_entry.py +++ b/pre_commit_hooks/notify_duplicate_entry.py @@ -4,15 +4,23 @@ from typing import Sequence from pathlib import Path -def _check_duplicate_entry(json_contents, key): - json_dict = {} - duplicate_uuids = set() - for row in json_contents: - if row[key] not in json_dict: - json_dict[row[key]] = row + +def _check_duplicate_entry(json_entries, pkeys): + """ Check duplicate entry based on pkey criteria. + + :param json_entries: List of json entries + :param pkeys: List of Primary keys + :return: list of duplicated entry pkey value tuples + """ + unique_entries = set() + duplicate_entries = set() + for entry in json_entries: + pkey_value_tuple = tuple(entry[pkey] for pkey in pkeys) + if pkey_value_tuple not in unique_entries: + unique_entries.add(pkey_value_tuple) else: - duplicate_uuids.add(row[key]) - return duplicate_uuids, len(duplicate_uuids) + duplicate_entries.add(pkey_value_tuple) + return duplicate_entries, len(duplicate_entries) def main(argv: Optional[Sequence[str]] = None) -> int: @@ -21,19 +29,27 @@ def main(argv: Optional[Sequence[str]] = None) -> int: help='Names of the JSON files to check duplicate entries' ) table_uuid_mapping = { - 'action': 'uuid', 'env_property_group': 'uuid', - 'environment': 'uuid', 'environment_property': 'code', - 'report_summary': 'uuid', - 'runner': 'uuid', 'scenario': 'uuid', - 'sla': 'uuid', 'sla_scenario_association': 'sla', 'tag': 'uuid', - 'tag_action_association': 'tag_uuid', - 'tag_case_association': 'test_case_uuid', - 'teams': 'uuid', - 'test_case': 'uuid', - 'test_suit': 'uuid', 'test_supported_version': 'test_case_uuid', - 'testcase_workload_association': 'uuid', 'user': 'uuid', - 'user_tokens': 'user_token', 'workflow_task': 'workflow_id', - 'context': 'uuid', + 'action': ['uuid'], + 'env_property_group': ['uuid'], + 'environment': ['uuid'], + 'environment_property': ['code'], + 'report_summary': ['uuid'], + 'runner': ['uuid'], + 'scenario': ['uuid'], + 'sla': ['uuid'], + 'sla_scenario_association': ['sla', 'scenario'], + 'tag': ['uuid'], + 'tag_action_association': ['tag_uuid', 'action_uuid'], + 'tag_case_association': ['test_case_uuid', 'tag_uuid'], + 'teams': ['uuid'], + 'test_case': ['uuid'], + 'test_suit': ['uuid'], + 'test_supported_version': ['test_case_uuid', 'version'], + 'testcase_workload_association': ['uuid'], + 'user': ['uuid'], + 'user_tokens': ['user_token'], + 'workflow_task': ['workflow_id'], + 'context': ['uuid'], } args = vars(parser.parse_args(argv)) @@ -43,13 +59,13 @@ def main(argv: Optional[Sequence[str]] = None) -> int: for i in range(len(filenames)): json_file = filenames[i] file_name = Path(filenames[i]).stem - key = table_uuid_mapping[file_name] + pkeys = table_uuid_mapping[file_name] with open(json_file, encoding='UTF-8') as f: - contents = json.load(f) - duplicate_uuids, status = _check_duplicate_entry(contents, key) + json_entries = json.load(f) + duplicate_entries, status = _check_duplicate_entry(json_entries, pkeys) if status: - print(f"Duplicate UUIDs found - {duplicate_uuids} in file " + print(f"Duplicate entries found - {duplicate_entries} in file " f"{json_file}") flag = True From 25cba977cebbfe6fac2d72fa05655e2777091dc8 Mon Sep 17 00:00:00 2001 From: Deepanshu Bhatia Date: Mon, 12 Jun 2023 10:17:40 +0530 Subject: [PATCH 5/6] EIR-212: Add test sla association primary key --- pre_commit_hooks/notify_duplicate_entry.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pre_commit_hooks/notify_duplicate_entry.py b/pre_commit_hooks/notify_duplicate_entry.py index 7f277f4c..ebacf863 100644 --- a/pre_commit_hooks/notify_duplicate_entry.py +++ b/pre_commit_hooks/notify_duplicate_entry.py @@ -50,6 +50,10 @@ def main(argv: Optional[Sequence[str]] = None) -> int: 'user_tokens': ['user_token'], 'workflow_task': ['workflow_id'], 'context': ['uuid'], + 'test_sla_association': ['test_case', 'sla'], + 'teams_association': ['user_uuid', 'team_uuid'], + 'teams_resource_permission': ['team_uuid', 'resource_name'], + 'label': ['uuid'], } args = vars(parser.parse_args(argv)) From c6c470fe34a04ec33273f1c264ad404746907e80 Mon Sep 17 00:00:00 2001 From: Deepanshu Bhatia Date: Tue, 21 Nov 2023 18:51:23 +0530 Subject: [PATCH 6/6] VOER-543: Add primary key for authentication related tables --- pre_commit_hooks/notify_duplicate_entry.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pre_commit_hooks/notify_duplicate_entry.py b/pre_commit_hooks/notify_duplicate_entry.py index ebacf863..703d8a5f 100644 --- a/pre_commit_hooks/notify_duplicate_entry.py +++ b/pre_commit_hooks/notify_duplicate_entry.py @@ -54,6 +54,10 @@ def main(argv: Optional[Sequence[str]] = None) -> int: 'teams_association': ['user_uuid', 'team_uuid'], 'teams_resource_permission': ['team_uuid', 'resource_name'], 'label': ['uuid'], + 'authentication_config_rules': ['auth_type'], + 'authentication': ['uuid'], + 'user_authentication_association': + ['user_uuid', 'authentication_uuid'], } args = vars(parser.parse_args(argv)) @@ -63,10 +67,19 @@ def main(argv: Optional[Sequence[str]] = None) -> int: for i in range(len(filenames)): json_file = filenames[i] file_name = Path(filenames[i]).stem - pkeys = table_uuid_mapping[file_name] + if file_name not in table_uuid_mapping: + print( + f"Table {file_name} has no primary key specified to validate " + f"duplicate entries. Please update the plugin code in " + f"https://git.voereir.io/voereir/pre-commit-hooks" + ) + continue + + primary_keys = table_uuid_mapping[file_name] with open(json_file, encoding='UTF-8') as f: json_entries = json.load(f) - duplicate_entries, status = _check_duplicate_entry(json_entries, pkeys) + duplicate_entries, status = _check_duplicate_entry( + json_entries, primary_keys) if status: print(f"Duplicate entries found - {duplicate_entries} in file "