artesian-sdk 4.3.1.dev2__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 (148) 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_branch.sh +24 -0
  5. artesian_sdk-5.0.0.dev2/.github/workflows/validate_tag.sh +59 -0
  6. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/.gitignore +2 -0
  7. artesian_sdk-5.0.0.dev2/.vscode/extensions.json +9 -0
  8. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/.vscode/launch.json +2 -2
  9. artesian_sdk-5.0.0.dev2/.vscode/settings.json +21 -0
  10. artesian_sdk-5.0.0.dev2/CONTRIBUTING.md +126 -0
  11. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/PKG-INFO +10 -17
  12. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/README.md +4 -2
  13. artesian_sdk-5.0.0.dev2/benchmark/README.md +40 -0
  14. artesian_sdk-5.0.0.dev2/benchmark/bench_serde.py +132 -0
  15. artesian_sdk-5.0.0.dev2/benchmark/results/jsons-100k-memory.json +79 -0
  16. artesian_sdk-5.0.0.dev2/benchmark/results/jsons-1m.json +79 -0
  17. artesian_sdk-5.0.0.dev2/benchmark/results/msgspec-100k-memory.json +79 -0
  18. artesian_sdk-5.0.0.dev2/benchmark/results/msgspec-1m.json +79 -0
  19. artesian_sdk-5.0.0.dev2/pyproject.toml +116 -0
  20. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/renovate.json +2 -1
  21. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Exceptions.py +17 -29
  22. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/ExtractionRangeConfig.py +1 -2
  23. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferQuery.py +59 -86
  24. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferQueryParameters.py +15 -15
  25. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/GMEPublicOfferService.py +4 -5
  26. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Market.py +4 -0
  27. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Status.py +1 -0
  28. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/__init__.py +13 -13
  29. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/MarketDataService.py +72 -130
  30. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/ArtesianMetadataFacet.py +5 -5
  31. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/ArtesianSearchResults.py +4 -4
  32. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/CheckConversionResult.py +2 -3
  33. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/CurveRangeEntity.py +6 -6
  34. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DeleteData.py +5 -5
  35. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedCfg.py +3 -3
  36. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedTransformQueryValidation.py +2 -3
  37. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/DerivedTransformQueryValidationResponse.py +3 -3
  38. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataEntityInput.py +19 -30
  39. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataEntityOutput.py +9 -16
  40. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/PagedResult.py +3 -4
  41. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/TimeSerieData.py +5 -4
  42. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/UnitOfMeasure.py +1 -2
  43. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/UpsertData.py +28 -26
  44. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/__init__.py +29 -29
  45. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/__init__.py +9 -9
  46. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/__init__.py +38 -39
  47. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/ActualQuery.py +28 -41
  48. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/AuctionQuery.py +14 -18
  49. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/BidAskQuery.py +18 -20
  50. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/DefaultPartitionStrategy.py +17 -19
  51. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/MasQuery.py +19 -22
  52. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/QueryService.py +9 -10
  53. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/VersionedQuery.py +45 -89
  54. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_Query.py +40 -40
  55. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ActualQueryParameters.py +15 -17
  56. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/AuctionQueryParameters.py +8 -10
  57. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/BidAskQueryParameters.py +9 -11
  58. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ExtractionRangeConfig.py +7 -7
  59. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/MasQueryParameters.py +9 -11
  60. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/MostRecentSelectionConfig.py +10 -11
  61. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/QueryParameters.py +28 -33
  62. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionSelectionConfig.py +3 -3
  63. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionedQueryParameters.py +17 -19
  64. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionsRangeSelectionConfig.py +5 -6
  65. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/__init__.py +11 -11
  66. artesian_sdk-5.0.0.dev2/src/Artesian/_ClientsExecutor/ArtesianJsonSerializer.py +226 -0
  67. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/_ClientsExecutor/Client.py +34 -36
  68. artesian_sdk-5.0.0.dev2/src/Artesian/_ClientsExecutor/RequestExecutor.py +290 -0
  69. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/__init__.py +15 -17
  70. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/_version.py +3 -3
  71. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/PKG-INFO +10 -17
  72. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/SOURCES.txt +14 -2
  73. artesian_sdk-5.0.0.dev2/src/artesian_sdk.egg-info/requires.txt +4 -0
  74. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/scm_file_list.json +110 -97
  75. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestActual.py +51 -19
  76. artesian_sdk-5.0.0.dev2/tests/TestArtesianJsonSerializer.py +148 -0
  77. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestBidAsk.py +34 -12
  78. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestClientErrorHandling.py +38 -21
  79. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestGMEPO.py +66 -28
  80. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestMarketDataDeleteData.py +25 -26
  81. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestMarketDataService.py +139 -93
  82. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestMarketDataUpsertData.py +50 -27
  83. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestMas.py +15 -12
  84. artesian_sdk-5.0.0.dev2/tests/TestReleaseTags.py +48 -0
  85. artesian_sdk-5.0.0.dev2/tests/TestRequestExecutor.py +221 -0
  86. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/TestVersioned.py +35 -9
  87. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/tests/helpers.py +10 -9
  88. artesian_sdk-5.0.0.dev2/uv.lock +699 -0
  89. artesian_sdk-4.3.1.dev2/.flake8 +0 -13
  90. artesian_sdk-4.3.1.dev2/.github/workflows/python-tests.yml +0 -102
  91. artesian_sdk-4.3.1.dev2/.vscode/extensions.json +0 -10
  92. artesian_sdk-4.3.1.dev2/.vscode/settings.json +0 -10
  93. artesian_sdk-4.3.1.dev2/CONTRIBUTING.md +0 -21
  94. artesian_sdk-4.3.1.dev2/pyproject.toml +0 -165
  95. artesian_sdk-4.3.1.dev2/src/Artesian/_ClientsExecutor/ArtesianJsonSerializer.py +0 -136
  96. artesian_sdk-4.3.1.dev2/src/Artesian/_ClientsExecutor/RequestExecutor.py +0 -309
  97. artesian_sdk-4.3.1.dev2/src/artesian_sdk.egg-info/requires.txt +0 -14
  98. artesian_sdk-4.3.1.dev2/src/artesian_sdk.egg-info/scm_version.json +0 -8
  99. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/.github/dependabot.yml +0 -0
  100. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/CODEOWNERS +0 -0
  101. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/LICENSE +0 -0
  102. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestActual.py +0 -0
  103. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestAuction.py +0 -0
  104. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestBidAsk.py +0 -0
  105. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedCfg.py +0 -0
  106. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedCfgTransform.py +0 -0
  107. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestDerivedTransformQueryValidation.py +0 -0
  108. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestGMEOffers.py +0 -0
  109. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestMarketDataService.py +0 -0
  110. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestMas.py +0 -0
  111. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestSearchFacet.py +0 -0
  112. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestVersioned.py +0 -0
  113. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteActual.py +0 -0
  114. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteAuction.py +0 -0
  115. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteBidAsk.py +0 -0
  116. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteMas.py +0 -0
  117. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndDeleteVersioned.py +0 -0
  118. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryActual.py +0 -0
  119. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryAuction.py +0 -0
  120. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryBidAsk.py +0 -0
  121. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/samples/TestWriteDataAndQueryMas.py +0 -0
  122. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/setup.cfg +0 -0
  123. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/.gitignore +0 -0
  124. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/ArtesianConfig.py +0 -0
  125. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/ArtesianPolicyConfig.py +0 -0
  126. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/BaType.py +0 -0
  127. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/GenerationType.py +0 -0
  128. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Purpose.py +0 -0
  129. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Scope.py +0 -0
  130. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/UnitType.py +0 -0
  131. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/Zone.py +0 -0
  132. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/GMEPublicOffers/_Enum/__init__.py +0 -0
  133. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Granularity.py +0 -0
  134. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/CommonUnitOfMeasure.py +0 -0
  135. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Dto/MarketDataIdentifier.py +0 -0
  136. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/AggregationRule.py +0 -0
  137. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/ArtesianMetadataFacetType.py +0 -0
  138. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/DerivedAlgorithm.py +0 -0
  139. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/MarketDataType.py +0 -0
  140. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/MarketData/_Enum/UpsertMode.py +0 -0
  141. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/RelativeInterval.py +0 -0
  142. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/ExtractionRangeType.py +0 -0
  143. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/VersionSelectionType.py +0 -0
  144. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/Query/_QueryParameters/__init__.py +0 -0
  145. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/Artesian/_ClientsExecutor/__init__.py +0 -0
  146. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/dependency_links.txt +0 -0
  147. {artesian_sdk-4.3.1.dev2 → artesian_sdk-5.0.0.dev2}/src/artesian_sdk.egg-info/top_level.txt +0 -0
  148. {artesian_sdk-4.3.1.dev2 → 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,24 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ if [[ $# -ne 1 ]]; then
6
+ echo "::error::Usage: $0 <expected-branch>"
7
+ exit 2
8
+ fi
9
+
10
+ EXPECTED_BRANCH="$1"
11
+
12
+ git fetch origin "$EXPECTED_BRANCH"
13
+
14
+ COMMIT_SHA="$GITHUB_SHA"
15
+ if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then
16
+ COMMIT_SHA="$(git rev-parse "${GITHUB_REF}^{commit}")"
17
+ fi
18
+
19
+ if ! git merge-base --is-ancestor "$COMMIT_SHA" "origin/$EXPECTED_BRANCH"; then
20
+ echo "::error::Release tag does not point to a commit contained in $EXPECTED_BRANCH."
21
+ exit 1
22
+ fi
23
+
24
+ echo "Release commit is contained in $EXPECTED_BRANCH."
@@ -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
+ }