artesian-sdk 4.4.0b1__tar.gz → 5.0.0.dev2__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 (200) hide show
  1. artesian_sdk-5.0.0.dev2/.gitattributes +1 -0
  2. artesian_sdk-5.0.0.dev2/.github/workflows/copilot-setup-steps.yml +20 -0
  3. artesian_sdk-5.0.0.dev2/.github/workflows/python-tests.yml +404 -0
  4. artesian_sdk-5.0.0.dev2/.github/workflows/validate_tag.sh +59 -0
  5. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/.gitignore +2 -0
  6. artesian_sdk-5.0.0.dev2/.vscode/extensions.json +9 -0
  7. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/.vscode/launch.json +2 -2
  8. artesian_sdk-5.0.0.dev2/.vscode/settings.json +21 -0
  9. artesian_sdk-5.0.0.dev2/CONTRIBUTING.md +126 -0
  10. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/PKG-INFO +19 -688
  11. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/README.md +13 -673
  12. artesian_sdk-5.0.0.dev2/benchmark/README.md +40 -0
  13. artesian_sdk-5.0.0.dev2/benchmark/bench_serde.py +132 -0
  14. artesian_sdk-5.0.0.dev2/benchmark/results/jsons-100k-memory.json +79 -0
  15. artesian_sdk-5.0.0.dev2/benchmark/results/jsons-1m.json +79 -0
  16. artesian_sdk-5.0.0.dev2/benchmark/results/msgspec-100k-memory.json +79 -0
  17. artesian_sdk-5.0.0.dev2/benchmark/results/msgspec-1m.json +79 -0
  18. artesian_sdk-5.0.0.dev2/pyproject.toml +116 -0
  19. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/renovate.json +2 -1
  20. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestActual.py +1 -1
  21. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryBidAsk.py +6 -6
  22. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Exceptions.py +17 -29
  23. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/ExtractionRangeConfig.py +1 -2
  24. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferQuery.py +54 -86
  25. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferQueryParameters.py +15 -15
  26. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferService.py +4 -5
  27. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/__init__.py +13 -13
  28. artesian_sdk-5.0.0.dev2/src/Artesian/MarketData/MarketDataService.py +542 -0
  29. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/ArtesianMetadataFacet.py +5 -5
  30. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/ArtesianSearchResults.py +4 -4
  31. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/CheckConversionResult.py +2 -3
  32. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/CurveRangeEntity.py +6 -6
  33. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DeleteData.py +5 -5
  34. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedCfg.py +3 -3
  35. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedTransformQueryValidation.py +2 -3
  36. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedTransformQueryValidationResponse.py +3 -3
  37. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataEntityInput.py +19 -30
  38. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataEntityOutput.py +9 -16
  39. artesian_sdk-5.0.0.dev2/src/Artesian/MarketData/_Dto/PagedResult.py +30 -0
  40. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/TimeSerieData.py +5 -4
  41. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/UnitOfMeasure.py +1 -2
  42. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/UpsertData.py +28 -26
  43. artesian_sdk-5.0.0.dev2/src/Artesian/MarketData/_Dto/__init__.py +40 -0
  44. artesian_sdk-5.0.0.dev2/src/Artesian/MarketData/_Enum/__init__.py +15 -0
  45. artesian_sdk-5.0.0.dev2/src/Artesian/MarketData/__init__.py +53 -0
  46. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/ActualQuery.py +28 -42
  47. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/AuctionQuery.py +14 -19
  48. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/BidAskQuery.py +18 -21
  49. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/DefaultPartitionStrategy.py +17 -19
  50. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/MasQuery.py +19 -23
  51. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/QueryService.py +10 -15
  52. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/VersionedQuery.py +45 -90
  53. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_Query.py +38 -79
  54. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ActualQueryParameters.py +15 -17
  55. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/AuctionQueryParameters.py +8 -10
  56. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/BidAskQueryParameters.py +9 -11
  57. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ExtractionRangeConfig.py +7 -7
  58. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/MasQueryParameters.py +9 -11
  59. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/MostRecentSelectionConfig.py +10 -11
  60. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/QueryParameters.py +28 -35
  61. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionSelectionConfig.py +3 -3
  62. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionedQueryParameters.py +17 -19
  63. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionsRangeSelectionConfig.py +5 -6
  64. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/__init__.py +11 -11
  65. artesian_sdk-5.0.0.dev2/src/Artesian/_ClientsExecutor/ArtesianJsonSerializer.py +226 -0
  66. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/_ClientsExecutor/Client.py +34 -36
  67. artesian_sdk-5.0.0.dev2/src/Artesian/_ClientsExecutor/RequestExecutor.py +290 -0
  68. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/__init__.py +15 -17
  69. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/_version.py +2 -2
  70. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/PKG-INFO +19 -688
  71. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/SOURCES.txt +13 -47
  72. artesian_sdk-5.0.0.dev2/src/artesian_sdk.egg-info/requires.txt +4 -0
  73. artesian_sdk-5.0.0.dev2/src/artesian_sdk.egg-info/scm_file_list.json +133 -0
  74. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestActual.py +51 -19
  75. artesian_sdk-5.0.0.dev2/tests/TestArtesianJsonSerializer.py +148 -0
  76. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestBidAsk.py +34 -12
  77. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestClientErrorHandling.py +38 -21
  78. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestGMEPO.py +66 -28
  79. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestMarketDataDeleteData.py +25 -26
  80. artesian_sdk-5.0.0.dev2/tests/TestMarketDataService.py +430 -0
  81. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestMarketDataUpsertData.py +50 -27
  82. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestMas.py +15 -12
  83. artesian_sdk-5.0.0.dev2/tests/TestReleaseTags.py +48 -0
  84. artesian_sdk-5.0.0.dev2/tests/TestRequestExecutor.py +221 -0
  85. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/TestVersioned.py +35 -9
  86. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/helpers.py +10 -9
  87. artesian_sdk-5.0.0.dev2/uv.lock +699 -0
  88. artesian_sdk-4.4.0b1/.flake8 +0 -13
  89. artesian_sdk-4.4.0b1/.github/workflows/python-tests.yml +0 -586
  90. artesian_sdk-4.4.0b1/.github/workflows/validate_tag.sh +0 -41
  91. artesian_sdk-4.4.0b1/.vscode/extensions.json +0 -10
  92. artesian_sdk-4.4.0b1/.vscode/settings.json +0 -10
  93. artesian_sdk-4.4.0b1/CONTRIBUTING.md +0 -21
  94. artesian_sdk-4.4.0b1/pyproject.toml +0 -165
  95. artesian_sdk-4.4.0b1/samples/TestDataQuality.py +0 -93
  96. artesian_sdk-4.4.0b1/samples/TestDataQualityAssignment.py +0 -135
  97. artesian_sdk-4.4.0b1/samples/TestDataQualityCheckResultCheckSummary.py +0 -137
  98. artesian_sdk-4.4.0b1/samples/TestDataQualityNotificationAlert.py +0 -44
  99. artesian_sdk-4.4.0b1/samples/TestDataQualityNotificationAlertAssignement.py +0 -110
  100. artesian_sdk-4.4.0b1/samples/TestMarketDataOverride.py +0 -126
  101. artesian_sdk-4.4.0b1/samples/TestQualityNotificationAlert.py +0 -74
  102. artesian_sdk-4.4.0b1/src/Artesian/MarketData/MarketDataService.py +0 -2184
  103. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/ActualCompletenessAndFreshnessConfigDto.py +0 -16
  104. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/AlertScheduleEventsDto.py +0 -22
  105. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/CheckResultCheckSummaryDto.py +0 -40
  106. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/CheckResultExtract.py +0 -66
  107. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/CompletenessAndFreshnessConfigDto.py +0 -22
  108. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/CronScheduleDefinitionDto.py +0 -24
  109. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DataQualityRuleConfigDto.py +0 -16
  110. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DataQualityRuleDtoInput.py +0 -26
  111. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DataQualityRuleDtoOutput.py +0 -21
  112. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DataQualityStatusSummaryDto.py +0 -35
  113. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DqCheckChangeEventDto.py +0 -55
  114. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/DqRuleDqStatusSummaryDto.py +0 -20
  115. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/MailNotificationDto.py +0 -14
  116. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/MarketDataDqStatusSummaryDto.py +0 -25
  117. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/MarketDataEntityOutputEnriched.py +0 -30
  118. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/MarketDataQualityRuleAssignmentDto.py +0 -48
  119. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/OutlierAbsoluteBoundConfigDto.py +0 -25
  120. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/OutlierConfigDto.py +0 -18
  121. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/OutlierModelConfigDto.py +0 -20
  122. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/OutlierRefCurveConfigDto.py +0 -25
  123. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/OverrideMetadataEntry.py +0 -42
  124. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/PagedResult.py +0 -65
  125. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/PagedResultOverrideMetadataEntry.py +0 -10
  126. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/QualityNotificationAlertAssignmentDto.py +0 -53
  127. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/QualityNotificationAlertDto.py +0 -33
  128. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/RecordValidationConfigDto.py +0 -26
  129. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/ScheduleConfigDto.py +0 -19
  130. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/ScheduleDefinitionDto.py +0 -16
  131. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/TriggerConfigDto.py +0 -35
  132. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/UpsertCurveDataOverride.py +0 -34
  133. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/VersionedCompletenessAndFreshnessConfigDto.py +0 -30
  134. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Dto/__init__.py +0 -139
  135. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/AlertType.py +0 -8
  136. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/CheckAggregatedStatus.py +0 -9
  137. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/OutlierModel.py +0 -6
  138. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/OverrideKind.py +0 -6
  139. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/PeriodPrecision.py +0 -10
  140. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/RuleType.py +0 -6
  141. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/ScheduleDefinitionType.py +0 -5
  142. artesian_sdk-4.4.0b1/src/Artesian/MarketData/_Enum/__init__.py +0 -29
  143. artesian_sdk-4.4.0b1/src/Artesian/MarketData/__init__.py +0 -154
  144. artesian_sdk-4.4.0b1/src/Artesian/_ClientsExecutor/ArtesianJsonSerializer.py +0 -437
  145. artesian_sdk-4.4.0b1/src/Artesian/_ClientsExecutor/RequestExecutor.py +0 -309
  146. artesian_sdk-4.4.0b1/src/artesian_sdk.egg-info/requires.txt +0 -14
  147. artesian_sdk-4.4.0b1/tests/TestDataQualitySerialization.py +0 -163
  148. artesian_sdk-4.4.0b1/tests/TestMarketDataService.py +0 -1424
  149. artesian_sdk-4.4.0b1/tests/TestQueryOverrides.py +0 -118
  150. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/.github/dependabot.yml +0 -0
  151. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/.github/workflows/validate_branch.sh +0 -0
  152. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/CODEOWNERS +0 -0
  153. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/LICENSE +0 -0
  154. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestAuction.py +0 -0
  155. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestBidAsk.py +0 -0
  156. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedCfg.py +0 -0
  157. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedCfgTransform.py +0 -0
  158. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedTransformQueryValidation.py +0 -0
  159. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestGMEOffers.py +0 -0
  160. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestMarketDataService.py +0 -0
  161. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestMas.py +0 -0
  162. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestSearchFacet.py +0 -0
  163. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestVersioned.py +0 -0
  164. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteActual.py +0 -0
  165. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteAuction.py +0 -0
  166. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteBidAsk.py +0 -0
  167. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteMas.py +0 -0
  168. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteVersioned.py +0 -0
  169. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryActual.py +0 -0
  170. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryAuction.py +0 -0
  171. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryMas.py +0 -0
  172. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/setup.cfg +0 -0
  173. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/.gitignore +0 -0
  174. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/ArtesianConfig.py +0 -0
  175. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/ArtesianPolicyConfig.py +0 -0
  176. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/BaType.py +0 -0
  177. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/GenerationType.py +0 -0
  178. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Market.py +0 -0
  179. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Purpose.py +0 -0
  180. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Scope.py +0 -0
  181. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Status.py +0 -0
  182. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/UnitType.py +0 -0
  183. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Zone.py +0 -0
  184. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/__init__.py +0 -0
  185. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Granularity.py +0 -0
  186. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/CommonUnitOfMeasure.py +0 -0
  187. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataIdentifier.py +0 -0
  188. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/AggregationRule.py +0 -0
  189. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/ArtesianMetadataFacetType.py +0 -0
  190. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/DerivedAlgorithm.py +0 -0
  191. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/MarketDataType.py +0 -0
  192. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/UpsertMode.py +0 -0
  193. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/RelativeInterval.py +0 -0
  194. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ExtractionRangeType.py +0 -0
  195. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionSelectionType.py +0 -0
  196. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/__init__.py +0 -0
  197. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/Artesian/_ClientsExecutor/__init__.py +0 -0
  198. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/dependency_links.txt +0 -0
  199. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/top_level.txt +0 -0
  200. {artesian_sdk-4.4.0b1 → artesian_sdk-5.0.0.dev2}/tests/__init__.py +0 -0
@@ -0,0 +1 @@
1
+ .github/workflows/*.sh text eol=lf
@@ -0,0 +1,20 @@
1
+ name: Copilot Setup Steps
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ paths: [.github/workflows/copilot-setup-steps.yml]
7
+ pull_request:
8
+ paths: [.github/workflows/copilot-setup-steps.yml]
9
+
10
+ jobs:
11
+ copilot-setup-steps:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: read
15
+ steps:
16
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
17
+ with:
18
+ version: "0.12.23"
19
+ python-version: "3.14"
20
+ enable-cache: false
@@ -0,0 +1,404 @@
1
+ name: "Artesian SDK Python"
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ tags:
7
+ - "v[0-9]*.[0-9]*.[0-9]*"
8
+ pull_request:
9
+ branches: [main, master, develop, develop-beta]
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ test-matrix:
17
+ name: "Python ${{ matrix.python-version }} / ${{ matrix.os }}"
18
+ runs-on: ${{ matrix.os }}
19
+ # Test artifacts use a fixed version regardless of the release tag.
20
+ env:
21
+ SETUPTOOLS_SCM_PRETEND_VERSION: "0.0.0"
22
+
23
+ permissions:
24
+ contents: read
25
+
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
30
+ os: ["ubuntu-latest", "windows-latest", "macos-latest"]
31
+
32
+ steps:
33
+ - name: "Checkout"
34
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
35
+ with:
36
+ fetch-depth: 0
37
+
38
+ - name: Set up uv / Python ${{ matrix.python-version }}
39
+ uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
40
+ with:
41
+ python-version: ${{ matrix.python-version }}
42
+
43
+ - name: Install dependencies
44
+ id: install
45
+ run: uv sync --locked
46
+
47
+ - name: Run Ruff and Pyrefly
48
+ shell: bash
49
+ run: |
50
+ uv run --no-sync ruff check --target-version "py${PYTHON_VERSION//./}" --output-format github .
51
+ uv run --no-sync ruff format --check --target-version "py${PYTHON_VERSION//./}" .
52
+ uv run --no-sync pyrefly check --python-version "$PYTHON_VERSION" --output-format github
53
+ env:
54
+ PYTHON_VERSION: ${{ matrix.python-version }}
55
+
56
+ - name: Test Pytest
57
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
58
+ run: |
59
+ uv run --no-sync pytest --junitxml=junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
60
+
61
+ - name: Build package
62
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
63
+ run: uv build
64
+
65
+ - name: Upload pytest test results
66
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
67
+ if: always()
68
+ with:
69
+ name: test-results-build-${{ matrix.python-version }}-${{ matrix.os }}
70
+ path: junit/test-results-${{ matrix.python-version }}-${{ matrix.os }}.xml
71
+
72
+ - name: Upload build coverage
73
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
74
+ if: always()
75
+ with:
76
+ name: coverage-build-${{ matrix.python-version }}-${{ matrix.os }}
77
+ include-hidden-files: true
78
+ path: |
79
+ .coverage
80
+ coverage.xml
81
+
82
+ checks:
83
+ name: "Checks"
84
+ runs-on: ubuntu-latest
85
+ needs: [test-matrix]
86
+ if: always()
87
+
88
+ permissions:
89
+ contents: read
90
+ checks: write
91
+ code-quality: write
92
+ pull-requests: read
93
+ env:
94
+ SETUPTOOLS_SCM_PRETEND_VERSION: "0.0.0"
95
+
96
+ steps:
97
+ - name: "Checkout"
98
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
99
+ with:
100
+ fetch-depth: 0
101
+
102
+ - name: "Set up uv"
103
+ if: ${{ needs.test-matrix.result == 'success' }}
104
+ uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
105
+ with:
106
+ python-version: "3.14"
107
+
108
+ - name: "Install coverage tooling"
109
+ if: ${{ needs.test-matrix.result == 'success' }}
110
+ run: uv sync --locked --no-dev --group test
111
+
112
+ - name: "Download coverage artifacts"
113
+ if: ${{ needs.test-matrix.result == 'success' }}
114
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
115
+ with:
116
+ pattern: coverage-build-*
117
+ path: coverage
118
+
119
+ - name: "Create code coverage report"
120
+ if: ${{ needs.test-matrix.result == 'success' }}
121
+ shell: bash
122
+ run: |
123
+ uv run --no-sync coverage combine coverage/coverage-build-*/.coverage
124
+ uv run --no-sync coverage xml
125
+ uv run --no-sync coverage html
126
+ uv run --no-sync coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY"
127
+
128
+ - name: "Upload combined coverage"
129
+ if: ${{ needs.test-matrix.result == 'success' }}
130
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
131
+ with:
132
+ name: coverage-combined
133
+ path: |
134
+ coverage.xml
135
+ htmlcov/
136
+
137
+ - name: "Upload coverage to GitHub"
138
+ if: >
139
+ needs.test-matrix.result == 'success' &&
140
+ ((github.event_name == 'pull_request' &&
141
+ github.event.pull_request.head.repo.full_name == github.repository) ||
142
+ (github.event_name == 'push' && github.ref == 'refs/heads/master'))
143
+ uses: actions/upload-code-coverage@2b21a77928be8d5168c2b9581a67f2adbebacc52 # v1
144
+ with:
145
+ file: coverage.xml
146
+ language: Python
147
+ label: code-coverage/pytest
148
+
149
+ - name: "Download test result artifacts"
150
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
151
+ if: always()
152
+ with:
153
+ pattern: test-results-build-*
154
+ path: test-results
155
+ merge-multiple: true
156
+
157
+ - name: "Test Report"
158
+ uses: dorny/test-reporter@d1b5dff021aa968b288b02285a8bf47471c5928a # v3
159
+ if: always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
160
+ with:
161
+ name: Python Tests
162
+ path: "test-results/**/*.xml"
163
+ reporter: java-junit
164
+ fail-on-error: "true"
165
+ use-actions-summary: "true"
166
+
167
+ - name: "Require successful matrix"
168
+ if: always()
169
+ env:
170
+ MATRIX_RESULT: ${{ needs.test-matrix.result }}
171
+ run: test "$MATRIX_RESULT" = success
172
+
173
+ # Stable: v4.3.0 -> 4.3.0; tag commit must be contained in master.
174
+ # Development / RC: v5.0.0.dev1 / v5.0.0rc2; tag commit must be contained in master.
175
+ # Beta: v4.3.0b1 / v5.0.0b1; tag commit must be contained in develop-beta.
176
+ # The beta version must be the next minor or major after the latest master GA.
177
+ # PR preview: v4.3.0a69.post1 / v4.3.0a69.post2. The base version
178
+ # must match the latest master GA version; 69 is the PR number, and
179
+ # 1 / 2 are preview iterations. The tag must point to the unmerged PR
180
+ # head containing current master, not to a synthetic merge commit.
181
+ build-release:
182
+ name: "Build release"
183
+ runs-on: ubuntu-latest
184
+ permissions:
185
+ contents: read
186
+ needs: [checks]
187
+
188
+ if: >
189
+ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
190
+ startsWith(github.ref, 'refs/tags/v') &&
191
+ needs.checks.result == 'success'
192
+
193
+ steps:
194
+ - name: "Checkout"
195
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
196
+ with:
197
+ ref: ${{ github.sha }}
198
+ fetch-depth: 0
199
+
200
+ - name: "Validate release tag"
201
+ id: tag
202
+ shell: bash
203
+ run: |
204
+ TAG="$GITHUB_REF_NAME"
205
+ if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+a[0-9]+\.post[0-9]+$ ]]; then
206
+ KIND=preview
207
+ elif [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+b[0-9]+$ ]]; then
208
+ KIND=beta
209
+ elif [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$ ]]; then
210
+ KIND=dev
211
+ elif [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+rc[0-9]+$ ]]; then
212
+ KIND=rc
213
+ else
214
+ KIND=ga
215
+ fi
216
+ bash .github/workflows/validate_tag.sh "$TAG" "$KIND"
217
+ echo "kind=$KIND" >> "$GITHUB_OUTPUT"
218
+ echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
219
+
220
+ - name: "Validate release commit is contained in master"
221
+ if: steps.tag.outputs.kind == 'ga' || steps.tag.outputs.kind == 'dev' || steps.tag.outputs.kind == 'rc'
222
+ shell: bash
223
+ run: bash .github/workflows/validate_branch.sh "master"
224
+
225
+ - name: "Validate release commit is contained in develop-beta"
226
+ if: steps.tag.outputs.kind == 'beta'
227
+ shell: bash
228
+ run: bash .github/workflows/validate_branch.sh "develop-beta"
229
+
230
+ - name: "Validate next minor or major version"
231
+ if: steps.tag.outputs.kind == 'beta'
232
+ shell: bash
233
+ run: |
234
+ TAG="${GITHUB_REF_NAME}"
235
+
236
+ git fetch origin master --tags
237
+
238
+ MASTER_VERSION=$(
239
+ git tag --merged origin/master --sort=-version:refname |
240
+ grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' |
241
+ head -n 1 |
242
+ sed 's/^v//'
243
+ )
244
+
245
+ BETA_VERSION=$(echo "$TAG" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+)b[0-9]+$/\1/')
246
+
247
+ echo "Master GA version: $MASTER_VERSION"
248
+ echo "Beta version: $BETA_VERSION"
249
+
250
+ if [[ -z "$MASTER_VERSION" ]]; then
251
+ echo "::error::Could not determine the latest GA version on master."
252
+ exit 1
253
+ fi
254
+
255
+ MASTER_MAJOR=$(echo "$MASTER_VERSION" | cut -d. -f1)
256
+ MASTER_MINOR=$(echo "$MASTER_VERSION" | cut -d. -f2)
257
+ NEXT_MINOR="$((10#$MASTER_MINOR + 1))"
258
+ NEXT_MAJOR="$((10#$MASTER_MAJOR + 1))"
259
+
260
+ if [[ "$BETA_VERSION" != "${MASTER_MAJOR}.${NEXT_MINOR}.0" &&
261
+ "$BETA_VERSION" != "${NEXT_MAJOR}.0.0" ]]; then
262
+ echo "::error::Beta version $BETA_VERSION is not the next minor or major version after master GA $MASTER_VERSION."
263
+ echo "::error::Expected: ${MASTER_MAJOR}.${NEXT_MINOR}.0bN or ${NEXT_MAJOR}.0.0bN"
264
+ exit 1
265
+ fi
266
+
267
+ echo "Beta version $BETA_VERSION is the next minor or major version after master GA $MASTER_VERSION."
268
+
269
+ - name: "Validate preview source"
270
+ if: steps.tag.outputs.kind == 'preview'
271
+ shell: bash
272
+ run: |
273
+ git fetch origin master
274
+
275
+ if ! git merge-base --is-ancestor origin/master HEAD; then
276
+ echo "::error::PR Preview tag does not contain the current master."
277
+ exit 1
278
+ fi
279
+
280
+ PR_NUMBER="${GITHUB_REF_NAME#*a}"
281
+ PR_NUMBER="${PR_NUMBER%%.*}"
282
+ git fetch origin "refs/pull/$PR_NUMBER/head"
283
+
284
+ if git merge-base --is-ancestor HEAD origin/master ||
285
+ [[ "$(git rev-parse HEAD)" != "$(git rev-parse FETCH_HEAD^{commit})" ]]; then
286
+ echo "::error::PR Preview tag must point to the unmerged head of PR $PR_NUMBER."
287
+ exit 1
288
+ fi
289
+
290
+ - name: "Validate preview version"
291
+ if: steps.tag.outputs.kind == 'preview'
292
+ shell: bash
293
+ run: |
294
+ TAG="${GITHUB_REF_NAME}"
295
+
296
+ git fetch origin master --tags
297
+
298
+ MASTER_VERSION=$(
299
+ git tag --merged origin/master --sort=-version:refname |
300
+ grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' |
301
+ head -n 1 |
302
+ sed 's/^v//'
303
+ )
304
+
305
+ PREVIEW_VERSION=$(echo "$TAG" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+)a[0-9]+\.post[0-9]+$/\1/')
306
+
307
+ echo "Master GA version: $MASTER_VERSION"
308
+ echo "Preview version: $PREVIEW_VERSION"
309
+
310
+ if [[ -z "$MASTER_VERSION" ]]; then
311
+ echo "::error::Could not determine the latest GA version on master."
312
+ exit 1
313
+ fi
314
+
315
+ if [[ "$PREVIEW_VERSION" != "$MASTER_VERSION" ]]; then
316
+ echo "::error::PR Preview version $PREVIEW_VERSION does not match current master GA version $MASTER_VERSION."
317
+ exit 1
318
+ fi
319
+
320
+ echo "PR Preview version matches current master GA version: $MASTER_VERSION"
321
+
322
+ - name: "Record release source"
323
+ id: source
324
+ run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
325
+
326
+ - name: "Set up uv"
327
+ uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
328
+ with:
329
+ python-version: "3.14"
330
+
331
+ - name: "Build package"
332
+ env:
333
+ SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.tag.outputs.version }}
334
+ run: uv build
335
+
336
+ - name: "Record distribution hashes"
337
+ run: |
338
+ echo "Source commit: ${{ steps.source.outputs.sha }}" >> "$GITHUB_STEP_SUMMARY"
339
+ sha256sum dist/*.whl dist/*.tar.gz >> "$GITHUB_STEP_SUMMARY"
340
+
341
+ - name: "Upload release distributions"
342
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
343
+ with:
344
+ name: release-dist
345
+ path: |
346
+ dist/*.whl
347
+ dist/*.tar.gz
348
+ if-no-files-found: error
349
+
350
+ # See https://docs.astral.sh/uv/guides/integration/github/#publishing-to-pypi
351
+ # Only this job can obtain a publishing identity; do not check out or build here.
352
+ publish:
353
+ name: "Attest and publish to PyPI"
354
+ runs-on: ubuntu-latest
355
+ needs: [build-release]
356
+ if: >
357
+ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
358
+ startsWith(github.ref, 'refs/tags/v') &&
359
+ needs.build-release.result == 'success'
360
+ environment:
361
+ name: pypi
362
+ permissions:
363
+ contents: read
364
+ id-token: write
365
+ concurrency:
366
+ group: pypi-${{ github.ref }}
367
+ cancel-in-progress: false
368
+ steps:
369
+ - name: "Download release distributions"
370
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
371
+ with:
372
+ name: release-dist
373
+ path: dist
374
+
375
+ - name: "Check release filenames"
376
+ shell: python
377
+ run: |
378
+ import os
379
+ import re
380
+ from pathlib import Path
381
+
382
+ match = re.fullmatch(r"v\d+\.\d+\.\d+(?:b\d+|rc\d+|\.dev\d+|a\d+\.post\d+)?", os.environ["GITHUB_REF_NAME"])
383
+ if not match:
384
+ raise SystemExit("Invalid release tag")
385
+ version = match.group()[1:]
386
+ expected = {f"artesian_sdk-{version}-py3-none-any.whl", f"artesian_sdk-{version}.tar.gz"}
387
+ if {path.name for path in Path("dist").iterdir()} != expected:
388
+ raise SystemExit("Release distributions do not match the tag")
389
+
390
+ - name: "Set up pinned uv"
391
+ uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
392
+ with:
393
+ version: "0.12.23"
394
+ enable-cache: false
395
+
396
+ - name: "Generate PEP 740 publish attestations"
397
+ uses: astral-sh/attest-action@f589a42a7efb6fe400b4f400de60b4bc90390027 # v0.0.6
398
+ with:
399
+ paths: |
400
+ dist/*.whl
401
+ dist/*.tar.gz
402
+
403
+ - name: "Publish with required Trusted Publishing"
404
+ run: uv publish --no-config --trusted-publishing always --publish-url https://upload.pypi.org/legacy/
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ if [[ $# -ne 2 ]]; then
6
+ echo "::error::Usage: $0 <tag> <ga|beta|dev|rc|preview>"
7
+ exit 2
8
+ fi
9
+
10
+ TAG="$1"
11
+ TYPE="$2"
12
+
13
+ case "$TYPE" in
14
+ ga)
15
+ PATTERN='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$'
16
+ EXPECTED='vX.Y.Z'
17
+ ;;
18
+
19
+ beta)
20
+ PATTERN='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)b(0|[1-9][0-9]*)$'
21
+ EXPECTED='vX.Y.ZbN'
22
+ ;;
23
+
24
+ dev)
25
+ PATTERN='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.dev(0|[1-9][0-9]*)$'
26
+ EXPECTED='vX.Y.Z.devN'
27
+ ;;
28
+
29
+ rc)
30
+ PATTERN='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)rc(0|[1-9][0-9]*)$'
31
+ EXPECTED='vX.Y.ZrcN'
32
+ ;;
33
+
34
+ preview)
35
+ PATTERN='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)a(0|[1-9][0-9]*)\.post(0|[1-9][0-9]*)$'
36
+ EXPECTED='vX.Y.Za{PR_NUMBER}.post{ITERATION}'
37
+ ;;
38
+
39
+ *)
40
+ echo "::error::Unknown tag type: $TYPE"
41
+ exit 1
42
+ ;;
43
+ esac
44
+
45
+ if [[ ! "$TAG" =~ $PATTERN ]]; then
46
+ echo "::error::Invalid $TYPE release tag: $TAG"
47
+ echo "Expected format: $EXPECTED"
48
+ exit 1
49
+ fi
50
+
51
+ if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then
52
+ git fetch --no-tags origin "$GITHUB_REF"
53
+ if [[ "$(git rev-parse FETCH_HEAD^{commit})" != "$(git rev-parse HEAD)" ]]; then
54
+ echo "::error::Release tag no longer points to the checked-out commit."
55
+ exit 1
56
+ fi
57
+ fi
58
+
59
+ echo "Valid $TYPE release tag: $TAG"
@@ -47,6 +47,8 @@ coverage.xml
47
47
  *.cover
48
48
  .hypothesis/
49
49
  .pytest_cache/
50
+ .ruff_cache/
51
+ src/Artesian/_version.py
50
52
 
51
53
  # Translations
52
54
  *.mo
@@ -0,0 +1,9 @@
1
+ {
2
+ "recommendations": [
3
+ "charliermarsh.ruff",
4
+ "github.vscode-github-actions",
5
+ "meta.pyrefly",
6
+ "ms-python.python",
7
+ "ms-python.debugpy"
8
+ ]
9
+ }
@@ -2,7 +2,7 @@
2
2
  "configurations": [
3
3
  {
4
4
  "name": "Python: Current File",
5
- "type": "python",
5
+ "type": "debugpy",
6
6
  "request": "launch",
7
7
  "program": "${file}",
8
8
  "console": "integratedTerminal",
@@ -11,7 +11,7 @@
11
11
  },
12
12
  {
13
13
  "name": "Python: Debug Tests",
14
- "type": "python",
14
+ "type": "debugpy",
15
15
  "request": "launch",
16
16
  "program": "${file}",
17
17
  "purpose": ["debug-test"],
@@ -0,0 +1,21 @@
1
+ {
2
+ "python.testing.pytestEnabled": true,
3
+ "python.testing.unittestEnabled": false,
4
+ "python.defaultInterpreterPath": "${workspaceFolder}/.venv",
5
+ "python.languageServer": "None",
6
+ "pyrefly.pyreflyExecutable": "from-environment",
7
+ "python.pyrefly.diagnosticMode": "workspace",
8
+ "python.analysis.inlayHints": {
9
+ "callArgumentNames": "all",
10
+ "functionReturnTypes": true,
11
+ "variableTypes": true
12
+ },
13
+ "ruff.importStrategy": "fromEnvironment",
14
+ "editor.fontSize": 16,
15
+ "editor.formatOnPaste": true,
16
+ "editor.formatOnSave": true,
17
+ "[python]": {
18
+ "editor.defaultFormatter": "charliermarsh.ruff",
19
+ "editor.inlayHints.enabled": "on"
20
+ }
21
+ }
@@ -0,0 +1,126 @@
1
+ # How to Contribute
2
+
3
+ ## 1. Set up the environment
4
+
5
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/) using the
6
+ version in `[tool.uv].required-version` in `pyproject.toml`, then:
7
+
8
+ ```sh
9
+ uv sync --locked --python 3.14
10
+ ```
11
+
12
+ This creates `.venv` and installs the SDK, test dependencies, Ruff, and Pyrefly
13
+ from `uv.lock`. Select `.venv` as the Python interpreter in VS Code and
14
+ install the recommended extensions. Use Ruff for linting and formatting and
15
+ Pyrefly for type checking.
16
+ The [Pyrefly VS Code extension](https://pyrefly.org/en/docs/IDE/#vscode-extension-settings)
17
+ uses the locked environment binary, workspace diagnostics, and inlay hints for
18
+ argument names, inferred return types, and variable types.
19
+
20
+ Python 3.11 is the minimum supported **package** version. CI tests and lints
21
+ 3.11–3.14 on Linux, Windows, and macOS; development defaults to 3.14.
22
+ Development tools are defined only in the `dev` and `test`
23
+ dependency groups and installed from `uv.lock`.
24
+
25
+ ## 2. Run checks
26
+
27
+ ```sh
28
+ uv run --locked ruff check .
29
+ uv run --locked ruff format --check .
30
+ uv run --locked pyrefly check
31
+ uv run --locked pytest
32
+ uv build
33
+ ```
34
+
35
+ Tests use mocked HTTP responses; no live tenant or API key is needed. Pytest
36
+ discovers `Test*.py` files and writes JUnit XML, terminal coverage, `coverage.xml`
37
+ (Cobertura), and `htmlcov/`. Branch coverage is enabled; generated version code
38
+ is excluded.
39
+
40
+ To check compatibility on an older supported interpreter (including polyfills
41
+ and syntax/type compatibility), switch interpreters and run the same checks as CI:
42
+
43
+ ```sh
44
+ uv sync --locked --python 3.11
45
+ uv run --no-sync ruff check --target-version py311 .
46
+ uv run --no-sync ruff format --check --target-version py311 .
47
+ uv run --no-sync pyrefly check --python-version 3.11
48
+ uv run --no-sync pytest
49
+ ```
50
+
51
+ Repeat with 3.12 and 3.13 (and matching Ruff/Pyrefly flags); don't assume that
52
+ passing checks on 3.14 guarantees compatibility with earlier supported versions.
53
+ Run `uv sync --locked --python 3.14` to restore the development environment.
54
+ To update dependencies intentionally, use `uv lock --upgrade` (or
55
+ `uv lock --upgrade-package NAME`) and commit the resulting lockfile with any
56
+ `pyproject.toml` changes. Tool upgrades must also update their pinned constraints.
57
+
58
+ ## 3. Formatting and typing
59
+
60
+ Use Ruff's format-on-save integration or `uv run ruff format PATH` for edited
61
+ Python files. CI enforces formatting and linting for SDK source and tests;
62
+ samples remain excluded. Explicit `Any` is limited to the JSON wire-schema
63
+ compiler's runtime annotations and the test decorators' dynamic unittest instances.
64
+
65
+ `uv run --locked pyrefly check` checks the SDK and tests on the development Python
66
+ version without a diagnostic baseline. CI also checks each supported version.
67
+ Keep annotations accurate without
68
+ changing public method names, parameters, or runtime behavior.
69
+ Use `TypeVar` and `Generic[T]` for generic classes until the minimum supported
70
+ Python is 3.12; PEP 695's `class Name[T]` syntax cannot be parsed by Python 3.11.
71
+ DTOs use PEP 604 `T | None` annotations; the msgspec wire-schema compiler
72
+ resolves them on every supported Python version.
73
+ Unknown responses use `object` rather than `Any`, and nullable service results
74
+ include `None`. Preserve public import paths and wire formats when
75
+ changing internal typing.
76
+
77
+ ## 3.1 JSON wire format
78
+
79
+ `Artesian._ClientsExecutor.ArtesianJsonSerializer` maps DTO dataclasses to the
80
+ Artesian JSON wire format with msgspec: PascalCase keys, omitted `None` fields,
81
+ enums by name, and RFC 3339 datetimes (naive stays naive, UTC ends in `Z`,
82
+ zero microseconds are omitted). A `dict` field is sent as a JSON object unless
83
+ it is declared with `keyValueArrayField()`, which sends it (and every dict
84
+ nested in it) as `[{"Key": k, "Value": v}]`. Decoding into any `dict` accepts
85
+ both shapes. `benchmark/bench_serde.py` measures large payloads; see
86
+ `benchmark/README.md`.
87
+
88
+ ## 4. CI and coverage
89
+
90
+ The OS/Python matrix builds the package and runs Ruff, Pyrefly, and pytest for
91
+ every event. The single **Checks** job is the required PR check: it combines
92
+ coverage data, publishes test results, HTML/XML artifacts and a job summary,
93
+ and fails if the matrix or reporting fails. Native GitHub coverage uses a
94
+ job-scoped `code-quality: write` permission. PR checks run on GitHub's merge
95
+ commit; pushes to `master` establish the comparison baseline. Fork PRs still
96
+ run tests and produce coverage artifacts/summaries, but skip uploads
97
+ requiring write access. Preview tags use the same matrix and report their
98
+ tagged commit.
99
+
100
+ ## 5. Release tags
101
+
102
+ Use a `v` prefix and canonical, unpadded numeric components. The package
103
+ version on PyPI is the tag without `v`; no version remapping is performed.
104
+
105
+ - **Stable:** `vX.Y.Z` (for example, `v4.3.0`). The tagged commit must be
106
+ contained in `master`.
107
+ - **Development and release candidate:** `vX.Y.Z.devN` and `vX.Y.ZrcN`
108
+ (for example, `v5.0.0.dev1` and `v5.0.0rc2`). The tagged commit must be
109
+ contained in `master`. Standalone alpha tags such as `v5.0.0a1` are not
110
+ accepted.
111
+ - **Beta:** `vX.Y.ZbN` (for example, `v4.3.0b1` or `v5.0.0b1`). The tagged
112
+ commit must be contained in `develop-beta`. Compared with the latest stable
113
+ tag on `master`, the base version must be either the next minor
114
+ (`X.(Y+1).0`) or the next major (`(X+1).0.0`).
115
+ - **PR preview:** `vX.Y.ZaPR.postITER` (for example, `v4.3.0a69.post2`).
116
+ `X.Y.Z` must match the latest stable tag on `master`; `PR` is the pull
117
+ request number and `ITER` is the preview iteration. The tag must point
118
+ to that PR's current, unmerged head commit, which must contain current
119
+ `master`—not GitHub's synthetic PR merge commit.
120
+
121
+ Only a pushed release tag or a manual workflow dispatch **on a tag ref** can
122
+ build a release and publish, after the matrix and **Checks** job pass. The
123
+ release build verifies that the remote tag still points at the checked-out
124
+ commit. PRs and branch dispatches cannot publish. The protected publisher
125
+ checks that the wheel and sdist filenames match the release tag before upload;
126
+ review the build source SHA and distribution hashes before approving it.