stbkit-core 0.1.0a9.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. stbkit/core/__init__.py +12 -0
  2. stbkit/core/_internal/constants.py +42 -0
  3. stbkit/core/_internal/extension_utils.py +238 -0
  4. stbkit/core/_internal/io_text.py +48 -0
  5. stbkit/core/_internal/name_converter.py +170 -0
  6. stbkit/core/_internal/optional_dependencies/xmlschema_validator.py +163 -0
  7. stbkit/core/_internal/stb_logger.py +86 -0
  8. stbkit/core/_internal/transform/__init__.py +5 -0
  9. stbkit/core/_internal/transform/guid_tools.py +73 -0
  10. stbkit/core/_internal/transform/select.py +114 -0
  11. stbkit/core/_internal/xml_value_converter.py +16 -0
  12. stbkit/core/data_model/__init__.py +5 -0
  13. stbkit/core/data_model/_internal/filter_option.py +25 -0
  14. stbkit/core/data_model/_internal/stb_types.py +98 -0
  15. stbkit/core/data_model/_internal/type_validation.py +755 -0
  16. stbkit/core/data_model/common.py +967 -0
  17. stbkit/core/data_model/stb_v2_0_0.py +13633 -0
  18. stbkit/core/data_model/stb_v2_0_0.pyi +15327 -0
  19. stbkit/core/data_model/stb_v2_0_1.py +13702 -0
  20. stbkit/core/data_model/stb_v2_0_1.pyi +15450 -0
  21. stbkit/core/data_model/stb_v2_0_2.py +21677 -0
  22. stbkit/core/data_model/stb_v2_0_2.pyi +23319 -0
  23. stbkit/core/data_model/stb_v2_1_0.py +27541 -0
  24. stbkit/core/data_model/stb_v2_1_0.pyi +31553 -0
  25. stbkit/core/data_model/stb_v2_1_1.py +27577 -0
  26. stbkit/core/data_model/stb_v2_1_1.pyi +31590 -0
  27. stbkit/core/py.typed +0 -0
  28. stbkit/core/repository/__init__.py +67 -0
  29. stbkit/core/repository/_internal/ref_def_v2_0_2.py +191 -0
  30. stbkit/core/repository/_internal/ref_def_v2_1_0.py +216 -0
  31. stbkit/core/repository/_internal/ref_def_v2_1_1.py +216 -0
  32. stbkit/core/repository/repo_common.py +363 -0
  33. stbkit/core/repository/repo_v2_0_2.py +48 -0
  34. stbkit/core/repository/repo_v2_0_2.pyi +257 -0
  35. stbkit/core/repository/repo_v2_1_0.py +48 -0
  36. stbkit/core/repository/repo_v2_1_0.pyi +272 -0
  37. stbkit/core/repository/repo_v2_1_1.py +50 -0
  38. stbkit/core/repository/repo_v2_1_1.pyi +272 -0
  39. stbkit/core/serialization/__init__.py +21 -0
  40. stbkit/core/serialization/_dict_converter.py +1448 -0
  41. stbkit/core/serialization/config.py +114 -0
  42. stbkit/core/serialization/profiles.py +57 -0
  43. stbkit/core/stb_exceptions.py +203 -0
  44. stbkit/core/stb_io/__init__.py +17 -0
  45. stbkit/core/stb_io/_internal/__init__.py +5 -0
  46. stbkit/core/stb_io/_internal/loader.py +63 -0
  47. stbkit/core/stb_io/_internal/serializer.py +157 -0
  48. stbkit/core/stb_io/_internal/stream_reader.py +346 -0
  49. stbkit/core/stb_io/_internal/xml_io.py +482 -0
  50. stbkit/core/stb_reporting.py +1061 -0
  51. stbkit/core/stb_typing.py +61 -0
  52. stbkit/core/validation/__init__.py +9 -0
  53. stbkit/core/validation/_internal/common.py +78 -0
  54. stbkit/core/validation/_internal/schema_validator.py +294 -0
  55. stbkit/core/validation/_internal/validator.py +109 -0
  56. stbkit_core-0.1.0a9.dev1.dist-info/METADATA +121 -0
  57. stbkit_core-0.1.0a9.dev1.dist-info/RECORD +60 -0
  58. stbkit_core-0.1.0a9.dev1.dist-info/WHEEL +5 -0
  59. stbkit_core-0.1.0a9.dev1.dist-info/licenses/LICENSE +373 -0
  60. stbkit_core-0.1.0a9.dev1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,86 @@
1
+ # Copyright 2025-2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ import io
8
+ import logging
9
+ import sys
10
+ import time
11
+ from logging import Logger
12
+ from typing import Any, TextIO
13
+
14
+
15
+ def get_logger(
16
+ *,
17
+ logger: Logger | None = None,
18
+ file: str | TextIO | None = None,
19
+ silent: bool = False,
20
+ show_time: bool = False,
21
+ show_elapsed: bool = False,
22
+ name: str = "stb",
23
+ show_name: bool = False,
24
+ separator: str = ":",
25
+ level: int = logging.WARNING,
26
+ ) -> Logger:
27
+ """
28
+ ロガー、ファイル、標準出力、出力無しのいずれかに対応するLoggerを返す。
29
+ logger: Loggerオブジェクトを指定(優先)
30
+ file: ファイルパス(str)またはファイルオブジェクト(io.TextIOBase)を指定
31
+ silent: Trueなら出力無し(NullHandlerを返す)
32
+ show_time: Trueで時刻を表示
33
+ show_elapsed: Trueで経過時間を表示
34
+ name: ロガー名を指定
35
+ すべて未指定なら標準出力
36
+ """
37
+ log: Logger = logging.getLogger(name)
38
+ log.handlers.clear()
39
+ log.propagate = False
40
+
41
+ if silent:
42
+ log.addHandler(logging.NullHandler())
43
+ return log
44
+ if logger is not None:
45
+ return logger
46
+
47
+ if file is not None:
48
+ if isinstance(file, str):
49
+ handler: logging.Handler = logging.FileHandler(file)
50
+ elif isinstance(file, io.TextIOBase):
51
+ handler = logging.StreamHandler(file)
52
+ else:
53
+ raise TypeError("fileはstrまたはio.TextIOBaseで指定してください")
54
+ else:
55
+ handler = logging.StreamHandler(sys.stderr)
56
+
57
+ # フォーマットの組み立て
58
+ fmt_parts: list[str] = []
59
+ if show_time:
60
+ fmt_parts.append("%(asctime)s")
61
+ if show_elapsed:
62
+ fmt_parts.append("%(elapsed)s")
63
+ fmt_parts.append("%(levelname).1s")
64
+ if show_name:
65
+ fmt_parts.append("%(name)s")
66
+
67
+ fmt_parts.append("%(message)s")
68
+ fmt: str = separator.join(fmt_parts)
69
+
70
+ class ElapsedFormatter(logging.Formatter):
71
+ def __init__(self, fmt: str):
72
+ super().__init__(fmt)
73
+ self.start_time = time.time()
74
+
75
+ def format(self, record: Any) -> str:
76
+ if show_elapsed:
77
+ elapsed = time.time() - self.start_time
78
+ record.elapsed = f"{elapsed:.2f}s"
79
+ else:
80
+ record.elapsed = ""
81
+ return super().format(record)
82
+
83
+ handler.setFormatter(ElapsedFormatter(fmt))
84
+ log.addHandler(handler)
85
+ log.setLevel(level=level)
86
+ return log
@@ -0,0 +1,5 @@
1
+ # Copyright 2025-2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -0,0 +1,73 @@
1
+ # Copyright 2025-2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ import uuid
8
+ from collections.abc import Callable
9
+ from enum import Enum
10
+ from uuid import UUID
11
+
12
+ from ...data_model.common import StBridgeElement, _FieldKind
13
+ from ..name_converter import private_field_name
14
+
15
+
16
+ class UuidGenerateType(Enum):
17
+ AUTO = "auto"
18
+ UUID4 = "uuid4"
19
+ UUID7 = "uuid7"
20
+
21
+
22
+ _uuid7: Callable[[], UUID] | None = getattr(uuid, "uuid7", None)
23
+
24
+
25
+ def generate_uuid(generate_type: UuidGenerateType = UuidGenerateType.AUTO) -> UUID:
26
+ match generate_type:
27
+ case UuidGenerateType.AUTO:
28
+ if callable(_uuid7):
29
+ return _uuid7()
30
+ return uuid.uuid4()
31
+ case UuidGenerateType.UUID7:
32
+ if callable(_uuid7):
33
+ return _uuid7()
34
+ raise RuntimeError("UUID7の利用はPython 3.14以降である必要があります")
35
+ case UuidGenerateType.UUID4:
36
+ return uuid.uuid4()
37
+
38
+
39
+ def assign_guid_all(stb_element: StBridgeElement) -> None:
40
+ """子要素も含めたすべての要素にguidを割り当てる。"""
41
+ for field_key, field_info in stb_element._fields.items():
42
+ p_name: str = private_field_name(field_key)
43
+ if field_info.py_type == UUID or field_info.py_type == "UUID":
44
+ current_guid = getattr(stb_element, p_name)
45
+ if current_guid is None:
46
+ setattr(stb_element, p_name, uuid.uuid4())
47
+ elif field_info.kind == _FieldKind.ELEMENT:
48
+ child = getattr(stb_element, p_name)
49
+ if isinstance(child, list):
50
+ for c in child:
51
+ if isinstance(c, StBridgeElement):
52
+ assign_guid_all(c)
53
+ elif isinstance(child, StBridgeElement):
54
+ assign_guid_all(child)
55
+
56
+
57
+ def is_guid_assigned_all(stb_element: StBridgeElement) -> bool:
58
+ """全要素にguidが割り当てられているかを確認する。"""
59
+ for field_key, field_info in stb_element._fields.items():
60
+ p_name: str = private_field_name(field_key)
61
+ if field_info.py_type == UUID or field_info.py_type == "UUID":
62
+ current_guid = getattr(stb_element, p_name)
63
+ if current_guid is None:
64
+ return False
65
+ elif field_info.kind == _FieldKind.ELEMENT:
66
+ child = getattr(stb_element, p_name)
67
+ if isinstance(child, list):
68
+ for c in child:
69
+ if isinstance(c, StBridgeElement) and not is_guid_assigned_all(c):
70
+ return False
71
+ elif isinstance(child, StBridgeElement) and not is_guid_assigned_all(child):
72
+ return False
73
+ return True
@@ -0,0 +1,114 @@
1
+ # Copyright 2025-2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ """要素の抜粋を行う処理。
8
+
9
+ TODO:モジュール名や関数名を検討中。filterやextract等。
10
+ また、inputを編集するか、コピーしてreturnするか
11
+ """
12
+
13
+ from ...data_model._internal.filter_option import FilterOption, NameFilter
14
+ from ...data_model.common import (
15
+ StBridgeElement,
16
+ StBridgeRoot,
17
+ _FieldKind,
18
+ _StBridgeElementList,
19
+ )
20
+ from ...stb_reporting import Reporter
21
+ from ..name_converter import private_field_name
22
+
23
+
24
+ def select_elements(
25
+ stb: StBridgeRoot,
26
+ option: FilterOption,
27
+ *,
28
+ reporter: Reporter,
29
+ ) -> None:
30
+ """SelectOptionで指定した要素のみが残るようにStBridgeRootを編集する。"""
31
+
32
+ def _traverse(element: StBridgeElement) -> bool:
33
+ """再帰的に要素をたどり、選択オプションに基づいて要素や属性を削除する。
34
+ RETURN: 要素がinclude指定で残る場合True、そうでない場合False"""
35
+ has_include_element: bool = False
36
+ for key, field in element._fields.items():
37
+ child_has_include_element: bool = False
38
+ # 要素の場合
39
+ if field.kind == _FieldKind.ELEMENT:
40
+ value = getattr(element, private_field_name(key), None)
41
+ if not value:
42
+ continue
43
+ if isinstance(value, list) and len(value) > 0:
44
+ xml_name: str = value[0]._xml_name()
45
+ for item in value:
46
+ if isinstance(item, StBridgeElement):
47
+ child_has_include_element = (
48
+ child_has_include_element or _traverse(item)
49
+ )
50
+ elif isinstance(value, StBridgeElement):
51
+ xml_name = value._xml_name()
52
+ child_has_include_element = child_has_include_element or _traverse(
53
+ value
54
+ )
55
+ else:
56
+ continue
57
+ # include指定がある場合はそれ以外は除外
58
+ if child_has_include_element or (
59
+ option.global_element_filter.include
60
+ and xml_name in option.global_element_filter.include
61
+ ):
62
+ has_include_element = True
63
+ elif (
64
+ option.global_element_filter.include
65
+ and xml_name not in option.global_element_filter.include
66
+ ):
67
+ if field.max_occurs == 1:
68
+ setattr(element, private_field_name(key), None)
69
+ else:
70
+ setattr(
71
+ element,
72
+ private_field_name(key),
73
+ _StBridgeElementList(parent=element),
74
+ )
75
+ continue
76
+ # exclude指定がある場合は除外
77
+ if xml_name in option.global_element_filter.exclude:
78
+ if field.max_occurs == 1:
79
+ setattr(element, private_field_name(key), None)
80
+ else:
81
+ setattr(
82
+ element,
83
+ private_field_name(key),
84
+ _StBridgeElementList(parent=element),
85
+ )
86
+ continue
87
+
88
+ # 属性の場合
89
+ elif field.kind == _FieldKind.ATTRIBUTE:
90
+ xml_name = element._xml_name(key)
91
+ # 属性抽出オプション
92
+ attrs_opt: NameFilter = option.element_attribute_filters.get(
93
+ element._xml_name(), NameFilter()
94
+ )
95
+ if attrs_opt and xml_name in attrs_opt.exclude:
96
+ setattr(element, private_field_name(key), None)
97
+ continue
98
+ if (
99
+ attrs_opt
100
+ and attrs_opt.include
101
+ and xml_name not in attrs_opt.include
102
+ ):
103
+ setattr(element, private_field_name(key), None)
104
+ continue
105
+ # グローバル除外
106
+ if (
107
+ option.global_attribute_filter
108
+ and xml_name in option.global_attribute_filter.exclude
109
+ ):
110
+ setattr(element, private_field_name(key), None)
111
+ continue
112
+ return has_include_element
113
+
114
+ _traverse(stb)
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ from typing import Any
8
+ from uuid import UUID
9
+
10
+
11
+ def any_to_xml_str(value: Any) -> str:
12
+ if isinstance(value, UUID):
13
+ return value.hex
14
+ if isinstance(value, bool):
15
+ return "true" if value else "false"
16
+ return str(value)
@@ -0,0 +1,5 @@
1
+ # Copyright 2025-2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -0,0 +1,25 @@
1
+ # Copyright 2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ from dataclasses import dataclass, field
8
+
9
+
10
+ @dataclass
11
+ class NameFilter:
12
+ """
13
+ include, excludeのフィルター。同時指定時はexclude優先
14
+ """
15
+
16
+ include: list[str] = field(default_factory=list)
17
+ exclude: list[str] = field(default_factory=list)
18
+
19
+
20
+ @dataclass
21
+ class FilterOption:
22
+ global_attribute_filter: NameFilter = field(default_factory=NameFilter)
23
+ global_element_filter: NameFilter = field(default_factory=NameFilter)
24
+ element_attribute_filters: dict[str, NameFilter] = field(default_factory=dict)
25
+ element_child_filters: dict[str, NameFilter] = field(default_factory=dict)
@@ -0,0 +1,98 @@
1
+ # Copyright 2026 TAISEI CORPORATION
2
+ # SPDX-License-Identifier: MPL-2.0
3
+ # This Source Code Form is subject to the terms of the Mozilla Public
4
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+
7
+ import uuid
8
+ from enum import Enum, IntEnum, StrEnum
9
+
10
+ from ...stb_typing import (
11
+ Angle,
12
+ Length,
13
+ Monolist,
14
+ MonolistId,
15
+ MonolistLength,
16
+ NonNegativeInteger,
17
+ NonNegativeLength,
18
+ PositiveInteger,
19
+ PositiveIntegerList,
20
+ Ratio,
21
+ )
22
+
23
+
24
+ class DataType(Enum):
25
+ ANGLE = "Angle"
26
+ BOOL = "bool"
27
+ FLOAT = "float"
28
+ INT = "int"
29
+ INT_ENUM = "IntEnum"
30
+ LENGTH = "Length"
31
+ MONOLIST = "Monolist"
32
+ MONOLIST_LENGTH = "MonolistLength"
33
+ MONOLIST_ID = "MonolistId"
34
+ NON_NEGATIVE_INTEGER = "NonNegativeInteger"
35
+ NON_NEGATIVE_LENGTH = "NonNegativeLength"
36
+ POSITIVE_INTEGER = "PositiveInteger"
37
+ POSITIVE_INTEGER_LIST = "PositiveIntegerList"
38
+ RATIO = "Ratio"
39
+ STR = "str"
40
+ STR_ENUM = "StrEnum"
41
+ UUID = "UUID"
42
+
43
+ def to_type(
44
+ self,
45
+ ) -> type[
46
+ Angle
47
+ | bool
48
+ | float
49
+ | int
50
+ | IntEnum
51
+ | Length
52
+ | Monolist
53
+ | MonolistLength
54
+ | MonolistId
55
+ | NonNegativeInteger
56
+ | NonNegativeLength
57
+ | PositiveInteger
58
+ | PositiveIntegerList
59
+ | Ratio
60
+ | str
61
+ | StrEnum
62
+ | uuid.UUID
63
+ ]:
64
+ match self:
65
+ case DataType.ANGLE:
66
+ return Angle
67
+ case DataType.BOOL:
68
+ return bool
69
+ case DataType.FLOAT:
70
+ return float
71
+ case DataType.INT:
72
+ return int
73
+ case DataType.INT_ENUM:
74
+ return IntEnum
75
+ case DataType.LENGTH:
76
+ return Length
77
+ case DataType.MONOLIST:
78
+ return Monolist
79
+ case DataType.MONOLIST_LENGTH:
80
+ return MonolistLength
81
+ case DataType.MONOLIST_ID:
82
+ return MonolistId
83
+ case DataType.NON_NEGATIVE_INTEGER:
84
+ return NonNegativeInteger
85
+ case DataType.NON_NEGATIVE_LENGTH:
86
+ return NonNegativeLength
87
+ case DataType.POSITIVE_INTEGER:
88
+ return PositiveInteger
89
+ case DataType.POSITIVE_INTEGER_LIST:
90
+ return PositiveIntegerList
91
+ case DataType.RATIO:
92
+ return Ratio
93
+ case DataType.STR:
94
+ return str
95
+ case DataType.STR_ENUM:
96
+ return StrEnum
97
+ case DataType.UUID:
98
+ return uuid.UUID