From ad4331a4bd8b29fe1f91b048c6d606e515659cf4 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Mon, 7 Feb 2022 18:55:16 +0100 Subject: facilitate for including other schemas in submodule and expose them to other packages --- .gitmodules | 4 +- MANIFEST.in | 2 +- src/hydrilla/builder/build.py | 4 +- src/hydrilla/builder/schemas | 1 - src/hydrilla/schemas | 1 + src/hydrilla/util/__init__.py | 103 ++------------------------------------- src/hydrilla/util/_util.py | 109 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 119 insertions(+), 105 deletions(-) delete mode 160000 src/hydrilla/builder/schemas create mode 160000 src/hydrilla/schemas create mode 100644 src/hydrilla/util/_util.py diff --git a/.gitmodules b/.gitmodules index 98d2b26..3bd8177 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,8 +4,8 @@ # # Available under the terms of Creative Commons Zero v1.0 Universal. -[submodule "src/hydrilla_builder/schemas"] - path = src/hydrilla/builder/schemas +[submodule "src/hydrilla/schemas"] + path = src/hydrilla/schemas url = ../hydrilla-json-schemas [submodule "src/test/source-package-example"] path = src/test/source-package-example diff --git a/MANIFEST.in b/MANIFEST.in index 5c563b4..7b65971 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,6 @@ # # Available under the terms of Creative Commons Zero v1.0 Universal. -include src/hydrilla/builder/schemas/package_source-*.schema.json* +include src/hydrilla/schemas/*.schema.json* include src/test/source-package-example/* global-exclude .git .gitignore .gitmodules diff --git a/src/hydrilla/builder/build.py b/src/hydrilla/builder/build.py index d89ead3..dae5579 100644 --- a/src/hydrilla/builder/build.py +++ b/src/hydrilla/builder/build.py @@ -35,9 +35,7 @@ import jsonschema from .. import util -here = Path(__file__).resolve().parent -with open(here / 'schemas' / 'package_source-1.schema.json') as schema_file: - index_json_schema = json.load(schema_file) +index_json_schema = util.load_schema('package_source-1.schema.json') class FileReferenceError(Exception): """ diff --git a/src/hydrilla/builder/schemas b/src/hydrilla/builder/schemas deleted file mode 160000 index ca1de2e..0000000 --- a/src/hydrilla/builder/schemas +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ca1de2ed4a69a71f2f75552ade693d04ea1baa85 diff --git a/src/hydrilla/schemas b/src/hydrilla/schemas new file mode 160000 index 0000000..ca1de2e --- /dev/null +++ b/src/hydrilla/schemas @@ -0,0 +1 @@ +Subproject commit ca1de2ed4a69a71f2f75552ade693d04ea1baa85 diff --git a/src/hydrilla/util/__init__.py b/src/hydrilla/util/__init__.py index 72f73bc..d435c0a 100644 --- a/src/hydrilla/util/__init__.py +++ b/src/hydrilla/util/__init__.py @@ -1,101 +1,8 @@ -# SPDX-License-Identifier: AGPL-3.0-or-later +# SPDX-License-Identifier: CC0-1.0 -# Building Hydrilla packages. +# Copyright (C) 2022 Wojtek Kosior # -# This file is part of Hydrilla -# -# Copyright (C) 2021, 2022 Wojtek Kosior -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -# -# I, Wojtek Kosior, thereby promise not to sue for violation of this -# file's license. Although I request that you do not make use this code -# in a proprietary program, I am not going to enforce this in court. - -import re as _re -import json as _json - -from typing import Optional as _Optional - -_strip_comment_re = _re.compile(r''' -^ # match from the beginning of each line -( # catch the part before '//' comment - (?: # this group matches either a string or a single out-of-string character - [^"/] | - " - (?: # this group matches any in-a-string character - [^"\\] | # match any normal character - \\[^u] | # match any escaped character like '\f' or '\n' - \\u[a-fA-F0-9]{4} # match an escape - )* - " - )* -) -# expect either end-of-line or a comment: -# * unterminated strings will cause matching to fail -# * bad comment (with '/' instead of '//') will be indicated by second group -# having length 1 instead of 2 or 0 -(//?|$) -''', _re.VERBOSE) - -def strip_json_comments(text: str) -> str: - """ - Accept JSON text with optional C++-style ('//') comments and return the text - with comments removed. Consecutive slashes inside strings are handled - properly. A spurious single slash ('/') shall generate an error. Errors in - JSON itself shall be ignored. - """ - processed = 0 - stripped_text = [] - for line in text.split('\n'): - match = _strip_comment_re.match(line) - - if match is None: # unterminated string - # ignore this error, let json module report it - stripped = line - elif len(match[2]) == 1: - raise _json.JSONDecodeError('bad comment', text, - processed + len(match[1])) - else: - stripped = match[1] - - stripped_text.append(stripped) - processed += len(line) + 1 - - return '\n'.join(stripped_text) - -def normalize_version(ver: list[int]) -> list[int]: - """Strip right-most zeroes from 'ver'. The original list is not modified.""" - new_len = 0 - for i, num in enumerate(ver): - if num != 0: - new_len = i + 1 - - return ver[:new_len] - -def parse_version(ver_str: str) -> list[int]: - """ - Convert 'ver_str' into an array representation, e.g. for ver_str="4.6.13.0" - return [4, 6, 13, 0]. - """ - return [int(num) for num in ver_str.split('.')] +# Available under the terms of Creative Commons Zero v1.0 Universal. -def version_string(ver: list[int], rev: _Optional[int]=None) -> str: - """ - Produce version's string representation (optionally with revision), like: - 1.2.3-5 - No version normalization is performed. - """ - return '.'.join([str(n) for n in ver]) + ('' if rev is None else f'-{rev}') +from ._util import strip_json_comments, normalize_version, parse_version, \ + version_string, load_schema diff --git a/src/hydrilla/util/_util.py b/src/hydrilla/util/_util.py new file mode 100644 index 0000000..0ce62f6 --- /dev/null +++ b/src/hydrilla/util/_util.py @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Building Hydrilla packages. +# +# This file is part of Hydrilla +# +# Copyright (C) 2021, 2022 Wojtek Kosior +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# +# I, Wojtek Kosior, thereby promise not to sue for violation of this +# file's license. Although I request that you do not make use this code +# in a proprietary program, I am not going to enforce this in court. + +import re +import json + +from pathlib import Path +from typing import Optional + +here = Path(__file__).resolve().parent + +_strip_comment_re = re.compile(r''' +^ # match from the beginning of each line +( # catch the part before '//' comment + (?: # this group matches either a string or a single out-of-string character + [^"/] | + " + (?: # this group matches any in-a-string character + [^"\\] | # match any normal character + \\[^u] | # match any escaped character like '\f' or '\n' + \\u[a-fA-F0-9]{4} # match an escape + )* + " + )* +) +# expect either end-of-line or a comment: +# * unterminated strings will cause matching to fail +# * bad comment (with '/' instead of '//') will be indicated by second group +# having length 1 instead of 2 or 0 +(//?|$) +''', re.VERBOSE) + +def strip_json_comments(text: str) -> str: + """ + Accept JSON text with optional C++-style ('//') comments and return the text + with comments removed. Consecutive slashes inside strings are handled + properly. A spurious single slash ('/') shall generate an error. Errors in + JSON itself shall be ignored. + """ + processed = 0 + stripped_text = [] + for line in text.split('\n'): + match = _strip_comment_re.match(line) + + if match is None: # unterminated string + # ignore this error, let json module report it + stripped = line + elif len(match[2]) == 1: + raise json.JSONDecodeError('bad comment', text, + processed + len(match[1])) + else: + stripped = match[1] + + stripped_text.append(stripped) + processed += len(line) + 1 + + return '\n'.join(stripped_text) + +def normalize_version(ver: list[int]) -> list[int]: + """Strip right-most zeroes from 'ver'. The original list is not modified.""" + new_len = 0 + for i, num in enumerate(ver): + if num != 0: + new_len = i + 1 + + return ver[:new_len] + +def parse_version(ver_str: str) -> list[int]: + """ + Convert 'ver_str' into an array representation, e.g. for ver_str="4.6.13.0" + return [4, 6, 13, 0]. + """ + return [int(num) for num in ver_str.split('.')] + +def version_string(ver: list[int], rev: Optional[int]=None) -> str: + """ + Produce version's string representation (optionally with revision), like: + 1.2.3-5 + No version normalization is performed. + """ + return '.'.join([str(n) for n in ver]) + ('' if rev is None else f'-{rev}') + +def load_schema(schema_filename: str) -> dict: + """Find schema JSON file in '../schemas' and json.load() it.""" + with open(here.parent / 'schemas' / schema_filename, 'rt') as file_handle: + return json.load(file_handle) -- cgit v1.2.3