avrotize 2.20.5__tar.gz → 2.21.1__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 (170) hide show
  1. {avrotize-2.20.5 → avrotize-2.21.1}/PKG-INFO +1 -1
  2. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/_version.py +3 -3
  3. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython/dataclass_core.jinja +1 -1
  4. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython/test_class.jinja +2 -1
  5. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython.py +4 -2
  6. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp.py +2 -2
  7. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo/go_helpers.jinja +5 -0
  8. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo/go_test.jinja +6 -2
  9. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo.py +9 -0
  10. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava.py +86 -1
  11. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/dataclass_core.jinja +1 -1
  12. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/test_class.jinja +3 -6
  13. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython.py +41 -14
  14. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/class_core.ts.jinja +13 -1
  15. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/package.json.jinja +4 -1
  16. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/test_class.ts.jinja +3 -0
  17. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots.py +86 -24
  18. {avrotize-2.20.5 → avrotize-2.21.1}/LICENSE +0 -0
  19. {avrotize-2.20.5 → avrotize-2.21.1}/README.md +0 -0
  20. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/__init__.py +0 -0
  21. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/__main__.py +0 -0
  22. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/asn1toavro.py +0 -0
  23. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotize.py +0 -0
  24. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp/CMakeLists.txt.jinja +0 -0
  25. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp/build.bat.jinja +0 -0
  26. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp/build.sh.jinja +0 -0
  27. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp/dataclass_body.jinja +0 -0
  28. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp/vcpkg.json.jinja +0 -0
  29. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocpp.py +0 -0
  30. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/README.md.jinja +0 -0
  31. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/class_test.cs.jinja +0 -0
  32. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/dataclass_core.jinja +0 -0
  33. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/enum_test.cs.jinja +0 -0
  34. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/project.csproj.jinja +0 -0
  35. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/project.sln.jinja +0 -0
  36. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/run_coverage.ps1.jinja +0 -0
  37. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/run_coverage.sh.jinja +0 -0
  38. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp/testproject.csproj.jinja +0 -0
  39. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsharp.py +0 -0
  40. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotocsv.py +0 -0
  41. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotodatapackage.py +0 -0
  42. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotodb.py +0 -0
  43. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo/go_enum.jinja +0 -0
  44. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo/go_helpers.jinja +0 -0
  45. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo/go_struct.jinja +0 -0
  46. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo/go_test.jinja +0 -0
  47. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo/go_union.jinja +0 -0
  48. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotogo.py +0 -0
  49. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotographql.py +0 -0
  50. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotoiceberg.py +0 -0
  51. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojava/class_test.java.jinja +0 -0
  52. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojava/enum_test.java.jinja +0 -0
  53. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojava/testproject.pom.jinja +0 -0
  54. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojava.py +0 -0
  55. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojs.py +0 -0
  56. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojsons.py +0 -0
  57. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotojstruct.py +0 -0
  58. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotokusto.py +0 -0
  59. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotomd/README.md.jinja +0 -0
  60. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotomd.py +0 -0
  61. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotools.py +0 -0
  62. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotoparquet.py +0 -0
  63. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotoproto.py +0 -0
  64. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython/enum_core.jinja +0 -0
  65. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython/pyproject_toml.jinja +0 -0
  66. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotopython/test_enum.jinja +0 -0
  67. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotorust/dataclass_enum.rs.jinja +0 -0
  68. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotorust/dataclass_struct.rs.jinja +0 -0
  69. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotorust/dataclass_union.rs.jinja +0 -0
  70. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotorust.py +0 -0
  71. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/class_core.ts.jinja +0 -0
  72. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/class_test.ts.jinja +0 -0
  73. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/enum_core.ts.jinja +0 -0
  74. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/gitignore.jinja +0 -0
  75. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/index.ts.jinja +0 -0
  76. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/package.json.jinja +0 -0
  77. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots/tsconfig.json.jinja +0 -0
  78. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotots.py +0 -0
  79. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/avrotoxsd.py +0 -0
  80. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/cddltostructure.py +0 -0
  81. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/commands.json +0 -0
  82. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/common.py +0 -0
  83. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/constants.py +0 -0
  84. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/csvtoavro.py +0 -0
  85. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/datapackagetoavro.py +0 -0
  86. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/cpp/vcpkg/vcpkg.json +0 -0
  87. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/cs/net90/dependencies.csproj +0 -0
  88. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/go/go121/go.mod +0 -0
  89. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/java/jdk21/pom.xml +0 -0
  90. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/python/py312/requirements.txt +0 -0
  91. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/rust/stable/Cargo.toml +0 -0
  92. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependencies/typescript/node22/package.json +0 -0
  93. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependency_resolver.py +0 -0
  94. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/dependency_version.py +0 -0
  95. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/generic/generic.avsc +0 -0
  96. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/jsonstoavro.py +0 -0
  97. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/jsonstostructure.py +0 -0
  98. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/jstructtoavro.py +0 -0
  99. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/kstructtoavro.py +0 -0
  100. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/kustotoavro.py +0 -0
  101. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/openapitostructure.py +0 -0
  102. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/parquettoavro.py +0 -0
  103. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/proto2parser.py +0 -0
  104. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/proto3parser.py +0 -0
  105. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototoavro.py +0 -0
  106. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/any.avsc +0 -0
  107. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/api.avsc +0 -0
  108. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/duration.avsc +0 -0
  109. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/field_mask.avsc +0 -0
  110. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/struct.avsc +0 -0
  111. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/timestamp.avsc +0 -0
  112. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/type.avsc +0 -0
  113. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/prototypes/wrappers.avsc +0 -0
  114. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocddl.py +0 -0
  115. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp/CMakeLists.txt.jinja +0 -0
  116. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp/build.bat.jinja +0 -0
  117. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp/build.sh.jinja +0 -0
  118. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp/dataclass_body.jinja +0 -0
  119. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp/vcpkg.json.jinja +0 -0
  120. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocpp.py +0 -0
  121. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/class_test.cs.jinja +0 -0
  122. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/dataclass_core.jinja +0 -0
  123. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/enum_test.cs.jinja +0 -0
  124. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/json_structure_converters.cs.jinja +0 -0
  125. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/program.cs.jinja +0 -0
  126. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/project.csproj.jinja +0 -0
  127. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/project.sln.jinja +0 -0
  128. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/testproject.csproj.jinja +0 -0
  129. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsharp/tuple_converter.cs.jinja +0 -0
  130. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretocsv.py +0 -0
  131. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretodatapackage.py +0 -0
  132. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretodb.py +0 -0
  133. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo/go_enum.jinja +0 -0
  134. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo/go_interface.jinja +0 -0
  135. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretogo/go_struct.jinja +0 -0
  136. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretographql.py +0 -0
  137. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretoiceberg.py +0 -0
  138. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/choice_core.jinja +0 -0
  139. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/class_core.jinja +0 -0
  140. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/enum_core.jinja +0 -0
  141. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/equals_hashcode.jinja +0 -0
  142. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/pom.xml.jinja +0 -0
  143. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojava/tuple_core.jinja +0 -0
  144. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/class_core.js.jinja +0 -0
  145. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/enum_core.js.jinja +0 -0
  146. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/package.json.jinja +0 -0
  147. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/test_class.js.jinja +0 -0
  148. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/test_enum.js.jinja +0 -0
  149. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs/test_runner.js.jinja +0 -0
  150. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojs.py +0 -0
  151. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretojsons.py +0 -0
  152. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretokusto.py +0 -0
  153. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretomd/README.md.jinja +0 -0
  154. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretomd.py +0 -0
  155. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretoproto.py +0 -0
  156. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/enum_core.jinja +0 -0
  157. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/map_alias.jinja +0 -0
  158. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/pyproject_toml.jinja +0 -0
  159. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretopython/test_enum.jinja +0 -0
  160. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretorust/dataclass_enum.rs.jinja +0 -0
  161. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretorust/dataclass_struct.rs.jinja +0 -0
  162. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretorust/dataclass_union.rs.jinja +0 -0
  163. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretorust.py +0 -0
  164. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/enum_core.ts.jinja +0 -0
  165. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/gitignore.jinja +0 -0
  166. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/index.ts.jinja +0 -0
  167. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretots/tsconfig.json.jinja +0 -0
  168. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/structuretoxsd.py +0 -0
  169. {avrotize-2.20.5 → avrotize-2.21.1}/avrotize/xsdtoavro.py +0 -0
  170. {avrotize-2.20.5 → avrotize-2.21.1}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avrotize
3
- Version: 2.20.5
3
+ Version: 2.21.1
4
4
  Summary: Tools to convert from and to Avro Schema from various other schema languages.
5
5
  Author-email: Clemens Vasters <clemensv@microsoft.com>
6
6
  Requires-Python: >=3.10
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2.20.5'
32
- __version_tuple__ = version_tuple = (2, 20, 5)
31
+ __version__ = version = '2.21.1'
32
+ __version_tuple__ = version_tuple = (2, 21, 1)
33
33
 
34
- __commit_id__ = commit_id = 'g4811363b1'
34
+ __commit_id__ = commit_id = 'g9b9841dd3'
@@ -48,7 +48,7 @@ class {{ class_name }}:
48
48
  """
49
49
  {% for field in fields %}
50
50
  {%- set isdate = field.type == "datetime" or field.type == "typing.Optional[datetime.datetime]" %}
51
- {{ field.name }}: {{ field.type }}=dataclasses.field(kw_only=True{% if dataclasses_json_annotation %}, metadata=dataclasses_json.config(field_name="{{ field.original_name }}"{%- if isdate -%}, encoder=lambda d: datetime.datetime.isoformat(d) if d else None, decoder=lambda d:datetime.datetime.fromisoformat(d) if d else None, mm_field=fields.DateTime(format='iso'){%- endif -%}){%- endif %})
51
+ {{ field.name }}: {{ field.type }}=dataclasses.field(kw_only=True{% if dataclasses_json_annotation %}, metadata=dataclasses_json.config(field_name="{{ field.original_name }}"{%- if isdate -%}, encoder=lambda d: d.isoformat() if isinstance(d, datetime.datetime) else d if d else None, decoder=lambda d: datetime.datetime.fromisoformat(d) if isinstance(d, str) else d if d else None, mm_field=fields.DateTime(format='iso'){%- endif -%}){%- endif %})
52
52
  {%- endfor %}
53
53
  {% if avro_annotation %}
54
54
  AvroType: typing.ClassVar[avro.schema.Schema] = avro.schema.make_avsc_object(
@@ -12,7 +12,8 @@ from {{ package_name | lower }} import {{ class_name }}
12
12
 
13
13
  {%- for import_type in import_types if import_type not in ['decimal.Decimal', 'datetime.datetime', 'datetime.date', 'datetime.time', 'datetime.timedelta'] %}
14
14
  {%- set import_type_name = 'Test_'+import_type.split('.')[-1] %}
15
- {%- set import_package_name = 'test_'+'_'.join(import_type.split('.')[:-1]) | lower %}
15
+ {%- set flat_package = '_'.join(import_type.split('.')[:-1]) | lower %}
16
+ {%- set import_package_name = flat_package if flat_package.startswith('test_') else 'test_' + flat_package %}
16
17
 
17
18
  {%- if import_type.startswith('.') %}
18
19
  from .{{ import_package_name }} import {{ import_type_name }}
@@ -327,7 +327,8 @@ class AvroToPython:
327
327
  def generate_test_class(self, package_name: str, class_name: str, fields: List[Dict[str, str]], import_types: Set[str]) -> None:
328
328
  """Generates a unit test class for a Python data class"""
329
329
  test_class_name = f"Test_{class_name}"
330
- tests_package_name = "test_"+package_name.replace('.', '_').lower()
330
+ flat_package = package_name.replace('.', '_').lower()
331
+ tests_package_name = flat_package if flat_package.startswith('test_') else f"test_{flat_package}"
331
332
  test_class_definition = process_template(
332
333
  "avrotopython/test_class.jinja",
333
334
  package_name=package_name,
@@ -348,7 +349,8 @@ class AvroToPython:
348
349
  def generate_test_enum(self, package_name: str, class_name: str, symbols: List[str]) -> None:
349
350
  """Generates a unit test class for a Python enum"""
350
351
  test_class_name = f"Test_{class_name}"
351
- tests_package_name = "test_"+package_name.replace('.', '_').lower()
352
+ flat_package = package_name.replace('.', '_').lower()
353
+ tests_package_name = flat_package if flat_package.startswith('test_') else f"test_{flat_package}"
352
354
  test_class_definition = process_template(
353
355
  "avrotopython/test_enum.jinja",
354
356
  package_name=package_name,
@@ -2072,8 +2072,8 @@ class StructureToCSharp:
2072
2072
  if enum_values:
2073
2073
  for value in enum_values:
2074
2074
  if isinstance(value, str):
2075
- # Convert to PascalCase enum member name
2076
- symbol_name = ''.join(word.capitalize() for word in re.split(r'[_\-\s]+', value))
2075
+ # Convert to PascalCase enum member name - must match generate_enum logic
2076
+ symbol_name = pascal(str(value).replace('-', '_').replace(' ', '_'))
2077
2077
  symbols.append(symbol_name)
2078
2078
  else:
2079
2079
  # For numeric enums, use Value1, Value2, etc.
@@ -1,5 +1,10 @@
1
1
  package {{ base_package }}
2
2
 
3
+ {%- if needs_time_import %}
4
+
5
+ import "time"
6
+ {%- endif %}
7
+
3
8
  {%- for struct in structs %}
4
9
 
5
10
  // CreateInstance{{ struct.name }} creates a new instance of {{ struct.name }} with sample data
@@ -2,16 +2,16 @@ package {{ base_package }}
2
2
 
3
3
  import (
4
4
  "testing"
5
- {%- if json_annotation %}
5
+ {%- if json_annotation and kind == 'struct' %}
6
6
  "encoding/json"
7
7
  {%- endif %}
8
8
  )
9
9
 
10
10
  func Test{{ struct_name }}(t *testing.T) {
11
11
  {%- if kind == 'struct' %}
12
+ {%- if json_annotation %}
12
13
  instance := CreateInstance{{ struct_name }}()
13
14
 
14
- {%- if json_annotation %}
15
15
  // Test JSON marshaling
16
16
  data, err := json.Marshal(&instance)
17
17
  if err != nil {
@@ -56,6 +56,10 @@ func Test{{ struct_name }}(t *testing.T) {
56
56
  if fromDataGzip == nil {
57
57
  t.Fatal("FromData with gzip returned nil")
58
58
  }
59
+ {%- else %}
60
+ // Basic instance creation test (no JSON serialization without json annotation)
61
+ instance := CreateInstance{{ struct_name }}()
62
+ _ = instance // Verify instance creation works
59
63
  {%- endif %}
60
64
  {%- elif kind == 'enum' %}
61
65
  // Test enum values
@@ -523,6 +523,10 @@ class StructureToGo:
523
523
  v = f'float64({random.uniform(-100, 100)})'
524
524
  elif go_type == '[]byte':
525
525
  v = '[]byte("' + ''.join(random.choices(string.ascii_letters + string.digits, k=10)) + '")'
526
+ elif go_type == 'time.Time':
527
+ v = 'time.Now()'
528
+ elif go_type == 'time.Duration':
529
+ v = 'time.Hour'
526
530
  elif go_type.startswith('[]'):
527
531
  inner_type = go_type[2:]
528
532
  v = f'{go_type}{{{self.random_value(inner_type)}}}'
@@ -549,10 +553,15 @@ class StructureToGo:
549
553
  'enums': self.enums,
550
554
  'base_package': self.base_package,
551
555
  }
556
+ needs_time_import = False
552
557
  for struct in context['structs']:
553
558
  for field in struct['fields']:
554
559
  if 'value' not in field:
555
560
  field['value'] = self.random_value(field['type'])
561
+ # Check if time package is needed
562
+ if 'time.Time' in field['type'] or 'time.Duration' in field['type']:
563
+ needs_time_import = True
564
+ context['needs_time_import'] = needs_time_import
556
565
  helpers_file_name = os.path.join(self.output_dir, 'pkg', self.base_package, f"{self.base_package}_helpers.go")
557
566
  render_template('structuretogo/go_helpers.jinja', helpers_file_name, **context)
558
567
 
@@ -384,7 +384,12 @@ class StructureToJava:
384
384
  field_count=len(field_names)
385
385
  )
386
386
 
387
- class_definition = class_definition.rstrip() + equals_hashcode + "\n}\n"
387
+ # Generate createTestInstance() method for testing (only for non-abstract classes)
388
+ create_test_instance = ''
389
+ if not is_abstract:
390
+ create_test_instance = self.generate_create_test_instance_method(class_name, fields, schema_namespace)
391
+
392
+ class_definition = class_definition.rstrip() + create_test_instance + equals_hashcode + "\n}\n"
388
393
 
389
394
  if write_file:
390
395
  self.write_to_file(package, class_name, class_definition)
@@ -455,6 +460,86 @@ class StructureToJava:
455
460
  return str(value)
456
461
  return f"/* unsupported const value */"
457
462
 
463
+ def get_test_value(self, java_type: str) -> str:
464
+ """ Get a test value for a Java type """
465
+ # Handle arrays/lists
466
+ if java_type.startswith("List<") or java_type.startswith("ArrayList<"):
467
+ return "new java.util.ArrayList<>()"
468
+ if java_type.startswith("Map<"):
469
+ return "new java.util.HashMap<>()"
470
+ if java_type.endswith("[]"):
471
+ return f"new {java_type[:-2]}[0]"
472
+
473
+ # Primitive test values
474
+ test_values = {
475
+ 'String': '"test-string"',
476
+ 'string': '"test-string"',
477
+ 'int': '42',
478
+ 'Integer': '42',
479
+ 'long': '42L',
480
+ 'Long': '42L',
481
+ 'double': '3.14',
482
+ 'Double': '3.14',
483
+ 'float': '3.14f',
484
+ 'Float': '3.14f',
485
+ 'boolean': 'true',
486
+ 'Boolean': 'true',
487
+ 'byte': '(byte)0',
488
+ 'Byte': '(byte)0',
489
+ 'short': '(short)0',
490
+ 'Short': '(short)0',
491
+ 'BigInteger': 'java.math.BigInteger.ZERO',
492
+ 'BigDecimal': 'java.math.BigDecimal.ZERO',
493
+ 'byte[]': 'new byte[0]',
494
+ 'LocalDate': 'java.time.LocalDate.now()',
495
+ 'LocalTime': 'java.time.LocalTime.now()',
496
+ 'Instant': 'java.time.Instant.now()',
497
+ 'Duration': 'java.time.Duration.ZERO',
498
+ 'UUID': 'java.util.UUID.randomUUID()',
499
+ 'URI': 'java.net.URI.create("http://example.com")',
500
+ 'Object': 'new Object()',
501
+ 'void': 'null',
502
+ 'Void': 'null',
503
+ }
504
+
505
+ if java_type in test_values:
506
+ return test_values[java_type]
507
+
508
+ # Check if it's a generated type (enum or class)
509
+ if java_type in self.generated_types_java_package:
510
+ type_kind = self.generated_types_java_package[java_type]
511
+ if type_kind == "enum":
512
+ return f'{java_type}.values()[0]'
513
+ elif type_kind == "class":
514
+ return f'{java_type}.createTestInstance()'
515
+
516
+ # Default: try to instantiate
517
+ return f'new {java_type}()'
518
+
519
+ def generate_create_test_instance_method(self, class_name: str, fields: List[Dict], parent_package: str) -> str:
520
+ """ Generates a static createTestInstance method that creates a fully initialized instance """
521
+ method = f"\n{INDENT}/**\n{INDENT} * Creates a test instance with all required fields populated\n{INDENT} * @return a fully initialized test instance\n{INDENT} */\n"
522
+ method += f"{INDENT}public static {class_name} createTestInstance() {{\n"
523
+ method += f"{INDENT*2}{class_name} instance = new {class_name}();\n"
524
+
525
+ for field in fields:
526
+ # Skip const fields
527
+ if field.get('is_const', False):
528
+ continue
529
+
530
+ field_name = field['name']
531
+ field_type = field['type']
532
+
533
+ # Get a test value for this field
534
+ test_value = self.get_test_value(field_type)
535
+
536
+ # Setter name: set{Pascal(field_name)}
537
+ method += f"{INDENT*2}instance.set{pascal(field_name)}({test_value});\n"
538
+
539
+ method += f"{INDENT*2}return instance;\n"
540
+ method += f"{INDENT}}}\n"
541
+ return method
542
+
458
543
  def generate_enum(self, structure_schema: Dict, field_name: str, parent_package: str, write_file: bool) -> JavaType:
459
544
  """ Generates a Java enum from JSON Structure enum schema """
460
545
 
@@ -69,7 +69,7 @@ class {{ class_name }}{% if base_class or is_abstract %}({% if base_class %}{{ b
69
69
  {% endif %}
70
70
  {% for field in fields %}
71
71
  {%- set isdate = field.type == "datetime.datetime" or field.type == "typing.Optional[datetime.datetime]" %}
72
- {{ field.name }}: {{ field.type }}=dataclasses.field(kw_only=True{% if dataclasses_json_annotation %}, metadata=dataclasses_json.config(field_name="{{ field.original_name }}"{%- if isdate -%}, encoder=lambda d: datetime.datetime.isoformat(d) if d else None, decoder=lambda d:datetime.datetime.fromisoformat(d) if d else None, mm_field=fields.DateTime(format='iso'){%- endif -%}){%- endif %})
72
+ {{ field.name }}: {{ field.type }}=dataclasses.field(kw_only=True{% if dataclasses_json_annotation %}, metadata=dataclasses_json.config(field_name="{{ field.original_name }}"{%- if isdate -%}, encoder=lambda d: d.isoformat() if isinstance(d, datetime.datetime) else d if d else None, decoder=lambda d: datetime.datetime.fromisoformat(d) if isinstance(d, str) else d if d else None, mm_field=fields.DateTime(format='iso'){%- endif -%}){%- endif %})
73
73
  {%- endfor %}
74
74
 
75
75
  @classmethod
@@ -11,12 +11,9 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src
11
11
  from {{ package_name | lower }} import {{ class_name }}
12
12
 
13
13
  {%- for import_type in import_types if import_type not in ['decimal.Decimal', 'datetime.datetime', 'datetime.date', 'datetime.time', 'datetime.timedelta', 'uuid.UUID'] %}
14
- {%- set import_type_name = 'Test_'+import_type.split('.')[-1] %}
15
- {%- set import_package_name = 'test_'+'_'.join(import_type.split('.')[:-1]) | lower %}
16
-
17
- {%- if import_type.startswith('.') %}
18
- from .{{ import_package_name }} import {{ import_type_name }}
19
- {%- else %}
14
+ {%- set import_type_name = import_type.split('.')[-1] %}
15
+ {%- set import_package_name = '.'.join(import_type.split('.')[:-1]) | lower %}
16
+ {%- if import_package_name %}
20
17
  from {{ import_package_name }} import {{ import_type_name }}
21
18
  {%- endif -%}
22
19
  {%- endfor %}
@@ -39,6 +39,7 @@ class StructureToPython:
39
39
  self.schema_doc: JsonNode = None
40
40
  self.generated_types: Dict[str, str] = {}
41
41
  self.generated_structure_types: Dict[str, Dict[str, Union[str, Dict, List]]] = {}
42
+ self.generated_enum_symbols: Dict[str, List[str]] = {}
42
43
  self.type_dict: Dict[str, Dict] = {}
43
44
  self.definitions: Dict[str, Any] = {}
44
45
  self.schema_registry: Dict[str, Dict] = {}
@@ -285,6 +286,7 @@ class StructureToPython:
285
286
  class_name = pascal(explicit_name if explicit_name else structure_schema.get('name', 'UnnamedClass'))
286
287
  schema_namespace = structure_schema.get('namespace', parent_namespace)
287
288
  namespace = self.concat_namespace(self.base_package, schema_namespace).lower()
289
+ package_name = self.python_package_from_structure_type(schema_namespace, class_name)
288
290
  python_qualified_name = self.python_fully_qualified_name_from_structure_type(schema_namespace, class_name)
289
291
 
290
292
  if python_qualified_name in self.generated_types:
@@ -357,8 +359,8 @@ class StructureToPython:
357
359
  )
358
360
 
359
361
  if write_file:
360
- self.write_to_file(namespace, class_name, class_definition)
361
- self.generate_test_class(namespace, class_name, field_docstrings, import_types)
362
+ self.write_to_file(package_name, class_name, class_definition)
363
+ self.generate_test_class(package_name, class_name, field_docstrings, import_types)
362
364
 
363
365
  self.generated_types[python_qualified_name] = 'class'
364
366
  self.generated_structure_types[python_qualified_name] = structure_schema
@@ -423,6 +425,7 @@ class StructureToPython:
423
425
  class_name = pascal(structure_schema.get('name', field_name + 'Enum'))
424
426
  schema_namespace = structure_schema.get('namespace', parent_namespace)
425
427
  namespace = self.concat_namespace(self.base_package, schema_namespace).lower()
428
+ package_name = self.python_package_from_structure_type(schema_namespace, class_name)
426
429
  python_qualified_name = self.python_fully_qualified_name_from_structure_type(schema_namespace, class_name)
427
430
 
428
431
  if python_qualified_name in self.generated_types:
@@ -441,10 +444,11 @@ class StructureToPython:
441
444
  )
442
445
 
443
446
  if write_file:
444
- self.write_to_file(namespace, class_name, enum_definition)
445
- self.generate_test_enum(namespace, class_name, symbols)
447
+ self.write_to_file(package_name, class_name, enum_definition)
448
+ self.generate_test_enum(package_name, class_name, symbols)
446
449
 
447
450
  self.generated_types[python_qualified_name] = 'enum'
451
+ self.generated_enum_symbols[python_qualified_name] = symbols
448
452
  return python_qualified_name
449
453
 
450
454
  def generate_choice(self, structure_schema: Dict, parent_namespace: str,
@@ -511,6 +515,7 @@ class StructureToPython:
511
515
  class_name = pascal(structure_schema.get('name', 'UnnamedMap'))
512
516
  schema_namespace = structure_schema.get('namespace', parent_namespace)
513
517
  namespace = self.concat_namespace(self.base_package, schema_namespace).lower()
518
+ package_name = self.python_package_from_structure_type(schema_namespace, class_name)
514
519
  python_qualified_name = self.python_fully_qualified_name_from_structure_type(schema_namespace, class_name)
515
520
 
516
521
  if python_qualified_name in self.generated_types:
@@ -535,7 +540,7 @@ class StructureToPython:
535
540
  )
536
541
 
537
542
  if write_file:
538
- self.write_to_file(namespace, class_name, map_definition)
543
+ self.write_to_file(package_name, class_name, map_definition)
539
544
 
540
545
  self.generated_types[python_qualified_name] = 'map'
541
546
  return python_qualified_name
@@ -596,7 +601,24 @@ class StructureToPython:
596
601
  elif field_type.startswith('typing.Union['):
597
602
  field_type = resolve(field_type)
598
603
  return generate_value(field_type)
599
- return test_values.get(field_type, 'Test_' + field_type + '.create_instance()')
604
+ if field_type in test_values:
605
+ return test_values[field_type]
606
+ # Check if this is an enum type - use first symbol value
607
+ # Look up by fully qualified name or by short name (class name only)
608
+ enum_symbols = None
609
+ if field_type in self.generated_enum_symbols:
610
+ enum_symbols = self.generated_enum_symbols[field_type]
611
+ else:
612
+ # Try to find by short name (the field type might be just the class name)
613
+ for qualified_name, symbols in self.generated_enum_symbols.items():
614
+ if qualified_name.endswith('.' + field_type) or qualified_name == field_type:
615
+ enum_symbols = symbols
616
+ break
617
+ if enum_symbols:
618
+ return f"{field_type.split('.')[-1]}.{enum_symbols[0]}"
619
+ # For complex types, use None since fields are typically optional
620
+ # This avoids needing to construct nested objects with required args
621
+ return 'None'
600
622
 
601
623
  return generate_value(field_type)
602
624
 
@@ -604,7 +626,8 @@ class StructureToPython:
604
626
  import_types: Set[str]) -> None:
605
627
  """Generates a unit test class for a Python dataclass"""
606
628
  test_class_name = f"Test_{class_name}"
607
- tests_package_name = "test_" + package_name.replace('.', '_').lower()
629
+ # Use a simpler file naming scheme based on class name only
630
+ test_file_name = f"test_{class_name.lower()}"
608
631
  test_class_definition = process_template(
609
632
  "structuretopython/test_class.jinja",
610
633
  package_name=package_name,
@@ -617,7 +640,7 @@ class StructureToPython:
617
640
  )
618
641
 
619
642
  base_dir = os.path.join(self.output_dir, "tests")
620
- test_file_path = os.path.join(base_dir, f"{tests_package_name.replace('.', '_').lower()}.py")
643
+ test_file_path = os.path.join(base_dir, f"{test_file_name}.py")
621
644
  if not os.path.exists(os.path.dirname(test_file_path)):
622
645
  os.makedirs(os.path.dirname(test_file_path), exist_ok=True)
623
646
  with open(test_file_path, 'w', encoding='utf-8') as file:
@@ -626,7 +649,8 @@ class StructureToPython:
626
649
  def generate_test_enum(self, package_name: str, class_name: str, symbols: List[str]) -> None:
627
650
  """Generates a unit test class for a Python enum"""
628
651
  test_class_name = f"Test_{class_name}"
629
- tests_package_name = "test_" + package_name.replace('.', '_').lower()
652
+ # Use a simpler file naming scheme based on class name only
653
+ test_file_name = f"test_{class_name.lower()}"
630
654
  test_class_definition = process_template(
631
655
  "structuretopython/test_enum.jinja",
632
656
  package_name=package_name,
@@ -635,7 +659,7 @@ class StructureToPython:
635
659
  symbols=symbols
636
660
  )
637
661
  base_dir = os.path.join(self.output_dir, "tests")
638
- test_file_path = os.path.join(base_dir, f"{tests_package_name.replace('.', '_').lower()}.py")
662
+ test_file_path = os.path.join(base_dir, f"{test_file_name}.py")
639
663
  if not os.path.exists(os.path.dirname(test_file_path)):
640
664
  os.makedirs(os.path.dirname(test_file_path), exist_ok=True)
641
665
  with open(test_file_path, 'w', encoding='utf-8') as file:
@@ -643,9 +667,8 @@ class StructureToPython:
643
667
 
644
668
  def write_to_file(self, package: str, class_name: str, python_code: str):
645
669
  """Writes a Python class to a file"""
646
- # Add 'struct' module to the package path
647
- full_package = f"{package}.struct"
648
- parent_package_name = '.'.join(full_package.split('.')[:-1])
670
+ # The containing directory is the parent package (matches avrotopython.py)
671
+ parent_package_name = '.'.join(package.split('.')[:-1])
649
672
  parent_package_path = os.sep.join(parent_package_name.split('.')).lower()
650
673
  directory_path = os.path.join(self.output_dir, "src", parent_package_path)
651
674
  if not os.path.exists(directory_path):
@@ -758,7 +781,11 @@ class StructureToPython:
758
781
  def convert_structure_to_python(structure_schema_path, py_file_path, package_name='', dataclasses_json_annotation=False, avro_annotation=False):
759
782
  """Converts JSON Structure schema to Python dataclasses"""
760
783
  if not package_name:
761
- package_name = os.path.splitext(os.path.basename(structure_schema_path))[0].lower().replace('-', '_')
784
+ # Strip .json extension, then also strip .struct suffix if present (*.struct.json naming convention)
785
+ base_name = os.path.splitext(os.path.basename(structure_schema_path))[0]
786
+ if base_name.endswith('.struct'):
787
+ base_name = base_name[:-7] # Remove '.struct' suffix
788
+ package_name = base_name.lower().replace('-', '_')
762
789
 
763
790
  structure_to_python = StructureToPython(package_name, dataclasses_json_annotation=dataclasses_json_annotation, avro_annotation=avro_annotation)
764
791
  structure_to_python.convert(structure_schema_path, py_file_path)
@@ -19,7 +19,7 @@ export {% if is_abstract %}abstract {% endif %}class {{ class_name }}{% if base_
19
19
  /** {{ field.docstring }} */
20
20
  {%- if typedjson_annotation %}
21
21
  {%- set field_type = field.type_no_null %}
22
- @jsonMember({{ field_type if not field.is_primitive else 'String' if field_type == 'Date' else field_type | capitalize }})
22
+ @jsonMember({{ 'String' if field.is_enum else (field_type if not field.is_primitive else 'String' if field_type == 'Date' else field_type | capitalize) }})
23
23
  {%- endif %}
24
24
  public {{ field.name }}{% if field.is_optional %}?{% endif %}: {{ field.type_no_null }};
25
25
  {%- endfor %}
@@ -63,4 +63,16 @@ export {% if is_abstract %}abstract {% endif %}class {{ class_name }}{% if base_
63
63
  return result;
64
64
  }
65
65
  {%- endif %}
66
+
67
+ /**
68
+ * Creates an instance of {{ class_name }} with sample data for testing.
69
+ * @returns A new {{ class_name }} instance with sample values.
70
+ */
71
+ public static createInstance(): {{ class_name }} {
72
+ return new {{ class_name }}(
73
+ {%- for field in required_fields %}
74
+ {{ field.test_value }}{% if not loop.last %},{% endif %} // {{ field.name }}
75
+ {%- endfor %}
76
+ );
77
+ }
66
78
  }
@@ -31,6 +31,9 @@
31
31
  ],
32
32
  "testMatch": [
33
33
  "**/*.test.ts"
34
- ]
34
+ ],
35
+ "moduleNameMapper": {
36
+ "^(\\.{1,2}/.*)\\.js$": "$1"
37
+ }
35
38
  }
36
39
  }
@@ -3,6 +3,9 @@
3
3
  */
4
4
 
5
5
  import { {{ class_name }} } from '../src/{{ relative_path }}';
6
+ {%- for enum_type, enum_path in enum_imports.items() %}
7
+ import { {{ enum_type }} } from '{{ enum_path }}';
8
+ {%- endfor %}
6
9
 
7
10
  describe('{{ class_name }}', () => {
8
11
  it('should create an instance with required fields', () => {