EmbeddedProto 4.0.0b1__tar.gz

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 (69) hide show
  1. embeddedproto-4.0.0b1/EmbeddedProto/EmbeddedProto.py +122 -0
  2. embeddedproto-4.0.0b1/EmbeddedProto/Features.py +255 -0
  3. embeddedproto-4.0.0b1/EmbeddedProto/Field.py +1295 -0
  4. embeddedproto-4.0.0b1/EmbeddedProto/Oneof.py +74 -0
  5. embeddedproto-4.0.0b1/EmbeddedProto/ProtoFile.py +210 -0
  6. embeddedproto-4.0.0b1/EmbeddedProto/TypeDefinitions.py +367 -0
  7. embeddedproto-4.0.0b1/EmbeddedProto/__init__.py +0 -0
  8. embeddedproto-4.0.0b1/EmbeddedProto/__main__.py +28 -0
  9. embeddedproto-4.0.0b1/EmbeddedProto/config.py +173 -0
  10. embeddedproto-4.0.0b1/EmbeddedProto/custom_header.py +513 -0
  11. embeddedproto-4.0.0b1/EmbeddedProto/embedded_proto_options.proto +62 -0
  12. embeddedproto-4.0.0b1/EmbeddedProto/embedded_proto_options_pb2.py +37 -0
  13. embeddedproto-4.0.0b1/EmbeddedProto/field_options.py +344 -0
  14. embeddedproto-4.0.0b1/EmbeddedProto/main.py +316 -0
  15. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/BytesStringCallback.h +476 -0
  16. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/Defines.h +118 -0
  17. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/EmptyArray.h +81 -0
  18. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/Errors.h +53 -0
  19. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/FieldStringBytes.h +793 -0
  20. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/Fields.h +832 -0
  21. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/Functional.h +412 -0
  22. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/MessageCallback.h +688 -0
  23. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/MessageInterface.h +792 -0
  24. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/MessageSizeCalculator.h +109 -0
  25. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/MessageState.h +207 -0
  26. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/ReadBufferFixedSize.h +204 -0
  27. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/ReadBufferInterface.h +181 -0
  28. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/ReadBufferSection.h +232 -0
  29. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/RepeatedField.h +1053 -0
  30. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/RepeatedFieldCallback.h +432 -0
  31. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/RepeatedFieldFixedSize.h +367 -0
  32. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/Version.h +39 -0
  33. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/WireFormatter.h +852 -0
  34. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/WriteBufferFixedSize.h +114 -0
  35. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto/WriteBufferInterface.h +134 -0
  36. embeddedproto-4.0.0b1/EmbeddedProto/src/EmbeddedProto.h +55 -0
  37. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldBasic_Deserialize.h.jinja2 +26 -0
  38. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldBasic_GetSet.h.jinja2 +89 -0
  39. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldBytes_GetSet.h.jinja2 +86 -0
  40. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldEnum_Deserialize.h.jinja2 +50 -0
  41. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldEnum_GetSet.h.jinja2 +93 -0
  42. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldErrorRecursive_GetSet.h.jinja2 +29 -0
  43. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldMap_GetSet.h.jinja2 +203 -0
  44. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldMsg_Deserialize.h.jinja2 +44 -0
  45. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldMsg_GetSet.h.jinja2 +93 -0
  46. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldRepeated_GetSet.h.jinja2 +94 -0
  47. embeddedproto-4.0.0b1/EmbeddedProto/templates/FieldString_GetSet.h.jinja2 +86 -0
  48. embeddedproto-4.0.0b1/EmbeddedProto/templates/Field_DeserializePartial.h.jinja2 +33 -0
  49. embeddedproto-4.0.0b1/EmbeddedProto/templates/Field_Serialize.h.jinja2 +112 -0
  50. embeddedproto-4.0.0b1/EmbeddedProto/templates/Field_SerializePartial.h.jinja2 +119 -0
  51. embeddedproto-4.0.0b1/EmbeddedProto/templates/Header.h.jinja2 +108 -0
  52. embeddedproto-4.0.0b1/EmbeddedProto/templates/TypeDefEnum.h.jinja2 +45 -0
  53. embeddedproto-4.0.0b1/EmbeddedProto/templates/TypeDefMsg.h.jinja2 +791 -0
  54. embeddedproto-4.0.0b1/EmbeddedProto/templates/TypeOneof.h.jinja2 +178 -0
  55. embeddedproto-4.0.0b1/EmbeddedProto/version.json +3 -0
  56. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/PKG-INFO +141 -0
  57. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/SOURCES.txt +67 -0
  58. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/dependency_links.txt +1 -0
  59. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/entry_points.txt +3 -0
  60. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/requires.txt +5 -0
  61. embeddedproto-4.0.0b1/EmbeddedProto.egg-info/top_level.txt +1 -0
  62. embeddedproto-4.0.0b1/LICENSE +30 -0
  63. embeddedproto-4.0.0b1/LICENSES/GPL-3.0-only.txt +674 -0
  64. embeddedproto-4.0.0b1/LICENSES/LicenseRef-EmbeddedProto-Commercial.txt +12 -0
  65. embeddedproto-4.0.0b1/PKG-INFO +141 -0
  66. embeddedproto-4.0.0b1/README.md +123 -0
  67. embeddedproto-4.0.0b1/pyproject.toml +35 -0
  68. embeddedproto-4.0.0b1/setup.cfg +4 -0
  69. embeddedproto-4.0.0b1/setup.py +84 -0
@@ -0,0 +1,122 @@
1
+ #
2
+ # Copyright (C) 2020-2026 Embedded AMS B.V. - All Rights Reserved
3
+ #
4
+ # This file is part of Embedded Proto.
5
+ #
6
+ # Embedded Proto is dual licensed. You may use it under the terms of the
7
+ # GNU General Public License version 3 (GPLv3) as published by the Free
8
+ # Software Foundation, or under a commercial license from Embedded AMS B.V.
9
+ #
10
+ # Under the GPLv3 you must release the source code of
11
+ # any product you distribute that includes Embedded Proto or code
12
+ # generated by it. A commercial license removes that obligation.
13
+ # See <https://embeddedproto.com/pricing/>.
14
+ #
15
+ # Embedded Proto is distributed WITHOUT ANY WARRANTY; without even the
16
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ # See the LICENSE file in the root of the repository for details.
18
+ #
19
+ # SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-EmbeddedProto-Commercial
20
+ #
21
+ # Embedded AMS B.V., Hoorn, the Netherlands - info at EmbeddedProto dot com
22
+ #
23
+
24
+ import os
25
+ import shutil
26
+ import sys
27
+ import grpc_tools.protoc as protoc
28
+ from importlib import resources
29
+
30
+
31
+ def get_well_known_types_location():
32
+ # Obtain the location of the Protobuf well known types, they are a resource
33
+ # to the grpc-tools package the file system.
34
+ file_name = (
35
+ resources.files("grpc_tools") / "_proto"
36
+ ).resolve()
37
+ return str(file_name)
38
+
39
+
40
+ def _run_license_command(argv):
41
+ # Configure / verify the license token without running a build. Imported
42
+ # lazily so the normal protoc path does not pay for it.
43
+ import argparse
44
+ from EmbeddedProto import custom_header
45
+
46
+ parser = argparse.ArgumentParser(
47
+ prog="embeddedproto",
48
+ description="Configure the EmbeddedProto license token and server URL.")
49
+ parser.add_argument("--set-token", metavar="TOKEN", default=None,
50
+ help="Store this build token in the user config.")
51
+ parser.add_argument("--server-url", metavar="URL", default=None,
52
+ help="Store this license server URL (must be https://).")
53
+ parser.add_argument("--check-license", action="store_true",
54
+ help="Verify the configured token against the server; write nothing.")
55
+ args = parser.parse_args(argv)
56
+ return custom_header.configure(token=args.set_token, server_url=args.server_url,
57
+ check_only=args.check_license)
58
+
59
+
60
+ def get_options_proto_location():
61
+ # Obtain the folder holding embedded_proto_options.proto, it ships with this package.
62
+ return str(resources.files("EmbeddedProto").resolve())
63
+
64
+
65
+ def get_plugin_location(program):
66
+ # Obtain the path of the protoc-gen-eams plugin.
67
+ #
68
+ # protoc searches its plugins on PATH, and the folder holding the embeddedproto command is
69
+ # not always on it. A build system for instance may call the command by its full path
70
+ # without activating the virtual environment. Prefer the plugin installed next to the
71
+ # command, fall back to PATH, and leave the lookup to protoc when neither has it.
72
+ bin_dir = os.path.dirname(os.path.abspath(program))
73
+ return shutil.which("protoc-gen-eams", path=bin_dir) or shutil.which("protoc-gen-eams")
74
+
75
+
76
+ def build_protoc_argv(argv, program=sys.argv[0]):
77
+ # Turn the command line of embeddedproto into the one handed to protoc. The program is the
78
+ # path this command was started with, used to locate the plugin. It also becomes the first
79
+ # element of the result, protoc takes that element as its own name and skips it.
80
+ #
81
+ # The include paths for embedded_proto_options.proto and the Protobuf well known types
82
+ # (google/protobuf/descriptor.proto, imported by the options file) are always appended,
83
+ # so a user only lists the folders holding their own proto files. The flag
84
+ # --IncludeWellKnownTypes from earlier versions is accepted and ignored.
85
+ argv = [x for x in argv if x != "--IncludeWellKnownTypes"]
86
+ argv = argv + ["-I" + get_options_proto_location(), "-I" + get_well_known_types_location()]
87
+
88
+ # Check if a plugin is included
89
+ if not [x for x in argv if x.startswith("--plugin")]:
90
+ # If not add the EmbeddedProto plugin, by path when it can be found.
91
+ plugin = get_plugin_location(program)
92
+ argv.insert(0, "--plugin=protoc-gen-eams" + ("=" + plugin if plugin else ""))
93
+
94
+ return [program] + argv
95
+
96
+
97
+ def run_protoc(argv=sys.argv):
98
+ # Remove the program name
99
+ program = argv.pop(0)
100
+
101
+ # License configuration sub-commands, handled before protoc. These let
102
+ # `embeddedproto --set-token <KEY> [--server-url <URL>]` and
103
+ # `embeddedproto --check-license` manage the user config without a build.
104
+ _license_flags = ("--set-token", "--server-url", "--check-license")
105
+ if any(arg == flag or arg.startswith(flag + "=")
106
+ for arg in argv for flag in _license_flags):
107
+ sys.exit(_run_license_command(argv))
108
+
109
+ # Check if the --cpp-src-location parameter is present
110
+ if "--cpp-src-location" in argv:
111
+ # Get the location of the src folder
112
+ src_location = str((resources.files("EmbeddedProto") / "src").resolve())
113
+ print(src_location)
114
+ # Exit the script after printing the source location
115
+ return
116
+
117
+ # Hand the exit code of protoc to the caller, so build scripts notice a failed generation.
118
+ sys.exit(protoc.main(build_protoc_argv(argv, program)))
119
+
120
+
121
+ if __name__ == "__main__":
122
+ run_protoc(sys.argv)
@@ -0,0 +1,255 @@
1
+ #
2
+ # Copyright (C) 2020-2026 Embedded AMS B.V. - All Rights Reserved
3
+ #
4
+ # This file is part of Embedded Proto.
5
+ #
6
+ # Embedded Proto is dual licensed. You may use it under the terms of the
7
+ # GNU General Public License version 3 (GPLv3) as published by the Free
8
+ # Software Foundation, or under a commercial license from Embedded AMS B.V.
9
+ #
10
+ # Under the GPLv3 you must release the source code of
11
+ # any product you distribute that includes Embedded Proto or code
12
+ # generated by it. A commercial license removes that obligation.
13
+ # See <https://embeddedproto.com/pricing/>.
14
+ #
15
+ # Embedded Proto is distributed WITHOUT ANY WARRANTY; without even the
16
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ # See the LICENSE file in the root of the repository for details.
18
+ #
19
+ # SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-EmbeddedProto-Commercial
20
+ #
21
+ # Embedded AMS B.V., Hoorn, the Netherlands - info at EmbeddedProto dot com
22
+ #
23
+
24
+ # Protobuf editions feature-resolution layer.
25
+ #
26
+ # Protobuf editions (edition = "2023" / "2024") replace the proto2/proto3 syntax
27
+ # switch with per-element "features" that can be overridden at file -> message ->
28
+ # field / enum / oneof scope. The descriptor sent to a code generator carries only
29
+ # the *explicitly set* overrides; a non-C++ plugin must resolve the effective value
30
+ # itself by walking the scope chain and falling back to the edition's defaults.
31
+ #
32
+ # This module provides:
33
+ # * EditionProfile: per-edition default value of each feature + which feature
34
+ # fields are legal in that edition.
35
+ # * FeatureResolver: picks the profile for a file and resolves a feature for any
36
+ # scope (file / message / field) by merging explicit overrides over the
37
+ # defaults.
38
+ #
39
+ # Resolution only happens here; consuming the resolved values (changing generated
40
+ # code) is done by the individual feature tickets. ED-1 only introduces the layer.
41
+
42
+ # -----------------------------------------------------------------------------
43
+ # Edition numbers (mirror google.protobuf.descriptor_pb2.Edition).
44
+
45
+ EDITION_PROTO2 = 998
46
+ EDITION_PROTO3 = 999
47
+ EDITION_2023 = 1000
48
+ EDITION_2024 = 1001
49
+
50
+
51
+ # -----------------------------------------------------------------------------
52
+ # Feature value constants (mirror the google.protobuf.FeatureSet enums). Using
53
+ # named constants keeps the consuming tickets readable instead of comparing magic
54
+ # numbers.
55
+
56
+ class FieldPresence:
57
+ EXPLICIT = 1
58
+ IMPLICIT = 2
59
+ LEGACY_REQUIRED = 3
60
+
61
+
62
+ class EnumType:
63
+ OPEN = 1
64
+ CLOSED = 2
65
+
66
+
67
+ class RepeatedFieldEncoding:
68
+ PACKED = 1
69
+ EXPANDED = 2
70
+
71
+
72
+ class Utf8Validation:
73
+ VERIFY = 2
74
+ NONE = 3
75
+
76
+
77
+ class MessageEncoding:
78
+ LENGTH_PREFIXED = 1
79
+ DELIMITED = 2
80
+
81
+
82
+ class JsonFormat:
83
+ ALLOW = 1
84
+ LEGACY_BEST_EFFORT = 2
85
+
86
+
87
+ # The six core feature fields EmbeddedProto resolves. These are the fields on the
88
+ # google.protobuf.FeatureSet message that carry behavior for the wire format /
89
+ # code generation.
90
+ CORE_FEATURE_FIELDS = (
91
+ "field_presence",
92
+ "enum_type",
93
+ "repeated_field_encoding",
94
+ "utf8_validation",
95
+ "message_encoding",
96
+ "json_format",
97
+ )
98
+
99
+ # Edition 2024 added these feature fields. They are codegen / naming concerns with
100
+ # no runtime effect for EmbeddedProto, but they are only legal from edition 2024.
101
+ EDITION_2024_FEATURE_FIELDS = (
102
+ "enforce_naming_style",
103
+ "default_symbol_visibility",
104
+ )
105
+
106
+
107
+ # -----------------------------------------------------------------------------
108
+
109
+ class EditionProfile:
110
+ """Holds, for a single edition, the default value of every core feature and
111
+ the set of feature fields that may be explicitly set in that edition."""
112
+
113
+ def __init__(self, edition, defaults, legal_features):
114
+ self.edition = edition
115
+ # A complete mapping of every core feature field to its default value for
116
+ # this edition.
117
+ self.defaults = dict(defaults)
118
+ # The names of feature fields that are allowed to be explicitly set.
119
+ self.legal_features = set(legal_features)
120
+
121
+
122
+ # The default value of each core feature per edition. Editions are cumulative:
123
+ # 2024 keeps the 2023 core defaults and only adds new (codegen-only) features.
124
+ _PROTO3_DEFAULTS = {
125
+ "field_presence": FieldPresence.IMPLICIT,
126
+ "enum_type": EnumType.OPEN,
127
+ "repeated_field_encoding": RepeatedFieldEncoding.PACKED,
128
+ "utf8_validation": Utf8Validation.VERIFY,
129
+ "message_encoding": MessageEncoding.LENGTH_PREFIXED,
130
+ "json_format": JsonFormat.ALLOW,
131
+ }
132
+
133
+ _EDITION_2023_DEFAULTS = {
134
+ "field_presence": FieldPresence.EXPLICIT,
135
+ "enum_type": EnumType.OPEN,
136
+ "repeated_field_encoding": RepeatedFieldEncoding.PACKED,
137
+ "utf8_validation": Utf8Validation.VERIFY,
138
+ "message_encoding": MessageEncoding.LENGTH_PREFIXED,
139
+ "json_format": JsonFormat.ALLOW,
140
+ }
141
+
142
+ # Edition 2024 inherits the 2023 core defaults unchanged.
143
+ _EDITION_2024_DEFAULTS = dict(_EDITION_2023_DEFAULTS)
144
+
145
+ PROFILES = {
146
+ EDITION_PROTO3: EditionProfile(EDITION_PROTO3, _PROTO3_DEFAULTS, CORE_FEATURE_FIELDS),
147
+ EDITION_2023: EditionProfile(EDITION_2023, _EDITION_2023_DEFAULTS, CORE_FEATURE_FIELDS),
148
+ EDITION_2024: EditionProfile(
149
+ EDITION_2024, _EDITION_2024_DEFAULTS,
150
+ tuple(CORE_FEATURE_FIELDS) + EDITION_2024_FEATURE_FIELDS),
151
+ }
152
+
153
+
154
+ # -----------------------------------------------------------------------------
155
+
156
+ def detect_edition(file_descriptor):
157
+ """Map a FileDescriptorProto onto an edition number understood by PROFILES.
158
+ proto2 is rejected upstream; an unknown/absent syntax is treated as proto3."""
159
+ syntax = file_descriptor.syntax
160
+ if "editions" == syntax:
161
+ return file_descriptor.edition
162
+ # proto3 (syntax == "proto3") and the default empty syntax map to the proto3
163
+ # profile so the existing generation path becomes a special case of the same
164
+ # machinery.
165
+ return EDITION_PROTO3
166
+
167
+
168
+ def _feature_set_of(options):
169
+ """Return the FeatureSet sub-message of an *Options message, or None when the
170
+ options object does not carry a features field (older descriptor types)."""
171
+ if options is None:
172
+ return None
173
+ try:
174
+ return options.features
175
+ except AttributeError:
176
+ return None
177
+
178
+
179
+ # -----------------------------------------------------------------------------
180
+
181
+ class FeatureResolver:
182
+ """Resolves the effective value of each feature for a single proto file by
183
+ merging the explicitly set overrides over the edition defaults."""
184
+
185
+ def __init__(self, file_descriptor):
186
+ self.edition = detect_edition(file_descriptor)
187
+ if self.edition not in PROFILES:
188
+ raise Exception("Unsupported protobuf edition: " + str(self.edition))
189
+ self.profile = PROFILES[self.edition]
190
+
191
+ # Verify the file itself does not set a feature that is illegal in this
192
+ # edition, then compute the file-scope resolved feature set.
193
+ self._check_legality(file_descriptor.options, "file " + file_descriptor.name)
194
+ self.file_features = self._merge(self.profile.defaults, file_descriptor.options)
195
+
196
+ def _check_legality(self, options, scope_description):
197
+ """Raise when an options object explicitly sets a feature field that is not
198
+ legal in this edition (e.g. a 2024-only feature used in a 2023 file)."""
199
+ feature_set = _feature_set_of(options)
200
+ if feature_set is None:
201
+ return
202
+ for field_descriptor, _value in feature_set.ListFields():
203
+ name = field_descriptor.name
204
+ if name not in self.profile.legal_features:
205
+ raise Exception(
206
+ "The feature '" + name + "' set on " + scope_description +
207
+ " is not supported in edition " + str(self.edition) + ".")
208
+
209
+ def _merge(self, base_features, options):
210
+ """Return a new resolved feature dict: a copy of base_features with the
211
+ explicit overrides from options applied on top."""
212
+ result = dict(base_features)
213
+ feature_set = _feature_set_of(options)
214
+ if feature_set is not None:
215
+ for name in CORE_FEATURE_FIELDS:
216
+ if feature_set.HasField(name):
217
+ result[name] = getattr(feature_set, name)
218
+ return result
219
+
220
+ def merge(self, base_features, options, scope_description=""):
221
+ """Public merge used to derive a child scope's resolved features from its
222
+ parent's. Also enforces edition legality of the explicit overrides."""
223
+ self._check_legality(options, scope_description)
224
+ return self._merge(base_features, options)
225
+
226
+ def resolve(self, *option_holders):
227
+ """Resolve all core features from an ordered list of option holders given
228
+ outermost-first (e.g. file, enclosing message(s), field). Each holder is an
229
+ *Options message (or None). Returns a complete feature dict."""
230
+ result = dict(self.profile.defaults)
231
+ for options in option_holders:
232
+ result = self._merge(result, options)
233
+ return result
234
+
235
+ # -- typed accessors on a resolved feature dict ---------------------------
236
+
237
+ @staticmethod
238
+ def field_presence(resolved):
239
+ return resolved["field_presence"]
240
+
241
+ @staticmethod
242
+ def enum_type(resolved):
243
+ return resolved["enum_type"]
244
+
245
+ @staticmethod
246
+ def repeated_encoding(resolved):
247
+ return resolved["repeated_field_encoding"]
248
+
249
+ @staticmethod
250
+ def message_encoding(resolved):
251
+ return resolved["message_encoding"]
252
+
253
+ @staticmethod
254
+ def utf8_validation(resolved):
255
+ return resolved["utf8_validation"]