Project

General

Profile

« Previous | Next » 

Revision ad4331a4

Added by koszko over 1 year ago

facilitate for including other schemas in submodule and expose them to other packages

View differences:

.gitmodules
4 4
#
5 5
# Available under the terms of Creative Commons Zero v1.0 Universal.
6 6

  
7
[submodule "src/hydrilla_builder/schemas"]
8
	path = src/hydrilla/builder/schemas
7
[submodule "src/hydrilla/schemas"]
8
	path = src/hydrilla/schemas
9 9
	url = ../hydrilla-json-schemas
10 10
[submodule "src/test/source-package-example"]
11 11
	path = src/test/source-package-example
MANIFEST.in
4 4
#
5 5
# Available under the terms of Creative Commons Zero v1.0 Universal.
6 6

  
7
include src/hydrilla/builder/schemas/package_source-*.schema.json*
7
include src/hydrilla/schemas/*.schema.json*
8 8
include src/test/source-package-example/*
9 9
global-exclude .git .gitignore .gitmodules
src/hydrilla/builder/build.py
35 35

  
36 36
from .. import util
37 37

  
38
here = Path(__file__).resolve().parent
39
with open(here / 'schemas' / 'package_source-1.schema.json') as schema_file:
40
    index_json_schema = json.load(schema_file)
38
index_json_schema = util.load_schema('package_source-1.schema.json')
41 39

  
42 40
class FileReferenceError(Exception):
43 41
    """
src/hydrilla/builder/schemas
1
Subproject commit ca1de2ed4a69a71f2f75552ade693d04ea1baa85
src/hydrilla/schemas
1
Subproject commit ca1de2ed4a69a71f2f75552ade693d04ea1baa85
src/hydrilla/util/__init__.py
1
# SPDX-License-Identifier: AGPL-3.0-or-later
1
# SPDX-License-Identifier: CC0-1.0
2 2

  
3
# Building Hydrilla packages.
3
# Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org>
4 4
#
5
# This file is part of Hydrilla
6
#
7
# Copyright (C) 2021, 2022 Wojtek Kosior
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU Affero General Public License as
11
# published by the Free Software Foundation, either version 3 of the
12
# License, or (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
# GNU Affero General Public License for more details.
18
#
19
# You should have received a copy of the GNU Affero General Public License
20
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
#
22
#
23
# I, Wojtek Kosior, thereby promise not to sue for violation of this
24
# file's license. Although I request that you do not make use this code
25
# in a proprietary program, I am not going to enforce this in court.
26

  
27
import re as _re
28
import json as _json
29

  
30
from typing import Optional as _Optional
31

  
32
_strip_comment_re = _re.compile(r'''
33
^ # match from the beginning of each line
34
( # catch the part before '//' comment
35
  (?: # this group matches either a string or a single out-of-string character
36
    [^"/] |
37
    "
38
    (?: # this group matches any in-a-string character
39
      [^"\\] |          # match any normal character
40
      \\[^u] |          # match any escaped character like '\f' or '\n'
41
      \\u[a-fA-F0-9]{4} # match an escape
42
    )*
43
    "
44
  )*
45
)
46
# expect either end-of-line or a comment:
47
# * unterminated strings will cause matching to fail
48
# * bad comment (with '/' instead of '//') will be indicated by second group
49
#   having length 1 instead of 2 or 0
50
(//?|$)
51
''', _re.VERBOSE)
52

  
53
def strip_json_comments(text: str) -> str:
54
    """
55
    Accept JSON text with optional C++-style ('//') comments and return the text
56
    with comments removed. Consecutive slashes inside strings are handled
57
    properly. A spurious single slash ('/') shall generate an error. Errors in
58
    JSON itself shall be ignored.
59
    """
60
    processed = 0
61
    stripped_text = []
62
    for line in text.split('\n'):
63
        match = _strip_comment_re.match(line)
64

  
65
        if match is None: # unterminated string
66
            # ignore this error, let json module report it
67
            stripped = line
68
        elif len(match[2]) == 1:
69
            raise _json.JSONDecodeError('bad comment', text,
70
                                        processed + len(match[1]))
71
        else:
72
            stripped = match[1]
73

  
74
        stripped_text.append(stripped)
75
        processed += len(line) + 1
76

  
77
    return '\n'.join(stripped_text)
78

  
79
def normalize_version(ver: list[int]) -> list[int]:
80
    """Strip right-most zeroes from 'ver'. The original list is not modified."""
81
    new_len = 0
82
    for i, num in enumerate(ver):
83
        if num != 0:
84
            new_len = i + 1
85

  
86
    return ver[:new_len]
87

  
88
def parse_version(ver_str: str) -> list[int]:
89
    """
90
    Convert 'ver_str' into an array representation, e.g. for ver_str="4.6.13.0"
91
    return [4, 6, 13, 0].
92
    """
93
    return [int(num) for num in ver_str.split('.')]
5
# Available under the terms of Creative Commons Zero v1.0 Universal.
94 6

  
95
def version_string(ver: list[int], rev: _Optional[int]=None) -> str:
96
    """
97
    Produce version's string representation (optionally with revision), like:
98
        1.2.3-5
99
    No version normalization is performed.
100
    """
101
    return '.'.join([str(n) for n in ver]) + ('' if rev is None else f'-{rev}')
7
from ._util import strip_json_comments, normalize_version, parse_version, \
8
    version_string, load_schema
src/hydrilla/util/_util.py
1
# SPDX-License-Identifier: AGPL-3.0-or-later
2

  
3
# Building Hydrilla packages.
4
#
5
# This file is part of Hydrilla
6
#
7
# Copyright (C) 2021, 2022 Wojtek Kosior
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU Affero General Public License as
11
# published by the Free Software Foundation, either version 3 of the
12
# License, or (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
# GNU Affero General Public License for more details.
18
#
19
# You should have received a copy of the GNU Affero General Public License
20
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
#
22
#
23
# I, Wojtek Kosior, thereby promise not to sue for violation of this
24
# file's license. Although I request that you do not make use this code
25
# in a proprietary program, I am not going to enforce this in court.
26

  
27
import re
28
import json
29

  
30
from pathlib import Path
31
from typing import Optional
32

  
33
here = Path(__file__).resolve().parent
34

  
35
_strip_comment_re = re.compile(r'''
36
^ # match from the beginning of each line
37
( # catch the part before '//' comment
38
  (?: # this group matches either a string or a single out-of-string character
39
    [^"/] |
40
    "
41
    (?: # this group matches any in-a-string character
42
      [^"\\] |          # match any normal character
43
      \\[^u] |          # match any escaped character like '\f' or '\n'
44
      \\u[a-fA-F0-9]{4} # match an escape
45
    )*
46
    "
47
  )*
48
)
49
# expect either end-of-line or a comment:
50
# * unterminated strings will cause matching to fail
51
# * bad comment (with '/' instead of '//') will be indicated by second group
52
#   having length 1 instead of 2 or 0
53
(//?|$)
54
''', re.VERBOSE)
55

  
56
def strip_json_comments(text: str) -> str:
57
    """
58
    Accept JSON text with optional C++-style ('//') comments and return the text
59
    with comments removed. Consecutive slashes inside strings are handled
60
    properly. A spurious single slash ('/') shall generate an error. Errors in
61
    JSON itself shall be ignored.
62
    """
63
    processed = 0
64
    stripped_text = []
65
    for line in text.split('\n'):
66
        match = _strip_comment_re.match(line)
67

  
68
        if match is None: # unterminated string
69
            # ignore this error, let json module report it
70
            stripped = line
71
        elif len(match[2]) == 1:
72
            raise json.JSONDecodeError('bad comment', text,
73
                                       processed + len(match[1]))
74
        else:
75
            stripped = match[1]
76

  
77
        stripped_text.append(stripped)
78
        processed += len(line) + 1
79

  
80
    return '\n'.join(stripped_text)
81

  
82
def normalize_version(ver: list[int]) -> list[int]:
83
    """Strip right-most zeroes from 'ver'. The original list is not modified."""
84
    new_len = 0
85
    for i, num in enumerate(ver):
86
        if num != 0:
87
            new_len = i + 1
88

  
89
    return ver[:new_len]
90

  
91
def parse_version(ver_str: str) -> list[int]:
92
    """
93
    Convert 'ver_str' into an array representation, e.g. for ver_str="4.6.13.0"
94
    return [4, 6, 13, 0].
95
    """
96
    return [int(num) for num in ver_str.split('.')]
97

  
98
def version_string(ver: list[int], rev: Optional[int]=None) -> str:
99
    """
100
    Produce version's string representation (optionally with revision), like:
101
        1.2.3-5
102
    No version normalization is performed.
103
    """
104
    return '.'.join([str(n) for n in ver]) + ('' if rev is None else f'-{rev}')
105

  
106
def load_schema(schema_filename: str) -> dict:
107
    """Find schema JSON file in '../schemas' and json.load() it."""
108
    with open(here.parent / 'schemas' / schema_filename, 'rt') as file_handle:
109
        return json.load(file_handle)

Also available in: Unified diff