artesian-sdk 3.1.2.dev3__tar.gz → 3.1.3__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 (104) hide show
  1. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.github/workflows/python-tests.yml +8 -0
  2. artesian-sdk-3.1.3/.vscode/extensions.json +10 -0
  3. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.vscode/settings.json +1 -3
  4. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/PKG-INFO +24 -1
  5. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/README.md +23 -0
  6. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/pyproject.toml +8 -1
  7. artesian-sdk-3.1.3/samples/TestSearchFacet.py +28 -0
  8. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Exceptions.py +1 -1
  9. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/GMEPublicOfferQuery.py +18 -25
  10. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/MarketDataService.py +87 -1
  11. artesian-sdk-3.1.3/src/Artesian/MarketData/_Dto/ArtesianMetadataFacet.py +33 -0
  12. artesian-sdk-3.1.3/src/Artesian/MarketData/_Dto/ArtesianSearchResults.py +20 -0
  13. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/__init__.py +5 -0
  14. artesian-sdk-3.1.3/src/Artesian/MarketData/_Enum/ArtesianMetadataFacetType.py +6 -0
  15. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Enum/__init__.py +2 -0
  16. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/__init__.py +9 -0
  17. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/DefaultPartitionStrategy.py +9 -4
  18. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_Query.py +1 -1
  19. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/QueryParameters.py +1 -1
  20. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/_ClientsExecutor/ArtesianJsonSerializer.py +1 -1
  21. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/_version.py +2 -2
  22. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/artesian_sdk.egg-info/PKG-INFO +24 -1
  23. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/artesian_sdk.egg-info/SOURCES.txt +5 -0
  24. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestGMEPO.py +37 -0
  25. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestMarketDataService.py +54 -0
  26. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/helpers.py +19 -2
  27. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.flake8 +0 -0
  28. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.github/dependabot.yml +0 -0
  29. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.github/workflows/dependency-review.yaml +0 -0
  30. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.gitignore +0 -0
  31. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/.vscode/launch.json +0 -0
  32. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/CONTRIBUTING.md +0 -0
  33. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/LICENSE +0 -0
  34. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestActual.py +0 -0
  35. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestAuction.py +0 -0
  36. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestBidAsk.py +0 -0
  37. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestGMEOffers.py +0 -0
  38. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestMarketDataService.py +0 -0
  39. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestMas.py +0 -0
  40. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestVersioned.py +0 -0
  41. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestWriteDataAndQueryActual.py +0 -0
  42. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestWriteDataAndQueryAuction.py +0 -0
  43. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestWriteDataAndQueryBidAsk.py +0 -0
  44. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/samples/TestWriteDataAndQueryMas.py +0 -0
  45. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/setup.cfg +0 -0
  46. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/.gitignore +0 -0
  47. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/ArtesianConfig.py +0 -0
  48. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/ArtesianPolicyConfig.py +0 -0
  49. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/ExtractionRangeConfig.py +0 -0
  50. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/GMEPublicOfferQueryParameters.py +0 -0
  51. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/GMEPublicOfferService.py +0 -0
  52. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/BaType.py +0 -0
  53. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/GenerationType.py +0 -0
  54. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/Market.py +0 -0
  55. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/Purpose.py +0 -0
  56. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/Scope.py +0 -0
  57. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/Status.py +0 -0
  58. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/UnitType.py +0 -0
  59. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/Zone.py +0 -0
  60. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/_Enum/__init__.py +0 -0
  61. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/GMEPublicOffers/__init__.py +0 -0
  62. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Granularity.py +0 -0
  63. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/CurveRangeEntity.py +0 -0
  64. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/MarketDataEntityInput.py +0 -0
  65. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/MarketDataEntityOutput.py +0 -0
  66. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/MarketDataIdentifier.py +0 -0
  67. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/PagedResult.py +0 -0
  68. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Dto/UpsertData.py +0 -0
  69. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Enum/AggregationRule.py +0 -0
  70. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/MarketData/_Enum/MarketDataType.py +0 -0
  71. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/ActualQuery.py +0 -0
  72. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/AuctionQuery.py +0 -0
  73. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/BidAskQuery.py +0 -0
  74. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/MasQuery.py +0 -0
  75. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/QueryService.py +0 -0
  76. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/RelativeInterval.py +0 -0
  77. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/VersionedQuery.py +0 -0
  78. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/ActualQueryParameters.py +0 -0
  79. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/AuctionQueryParameters.py +0 -0
  80. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/BidAskQueryParameters.py +0 -0
  81. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/ExtractionRangeConfig.py +0 -0
  82. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/ExtractionRangeType.py +0 -0
  83. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/MasQueryParameters.py +0 -0
  84. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/MostRecentSelectionConfig.py +0 -0
  85. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/VersionSelectionConfig.py +0 -0
  86. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/VersionSelectionType.py +0 -0
  87. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/VersionedQueryParameters.py +0 -0
  88. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/VersionsRangeSelectionConfig.py +0 -0
  89. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/_QueryParameters/__init__.py +0 -0
  90. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/Query/__init__.py +0 -0
  91. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/_ClientsExecutor/Client.py +0 -0
  92. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/_ClientsExecutor/RequestExecutor.py +0 -0
  93. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/_ClientsExecutor/__init__.py +0 -0
  94. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/Artesian/__init__.py +0 -0
  95. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/artesian_sdk.egg-info/dependency_links.txt +0 -0
  96. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/artesian_sdk.egg-info/requires.txt +0 -0
  97. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/src/artesian_sdk.egg-info/top_level.txt +0 -0
  98. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestActual.py +0 -0
  99. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestBidAsk.py +0 -0
  100. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestClientErrorHandling.py +0 -0
  101. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestMarketDataUpsertData.py +0 -0
  102. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestMas.py +0 -0
  103. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/TestVersioned.py +0 -0
  104. {artesian-sdk-3.1.2.dev3 → artesian-sdk-3.1.3}/tests/__init__.py +0 -0
@@ -36,6 +36,14 @@ jobs:
36
36
  run: |
37
37
  flake8 .
38
38
 
39
+ - uses: jordemort/action-pyright@v1
40
+ with:
41
+ github_token: ${{ secrets.GITHUB_TOKEN }}
42
+ reporter: github-check
43
+ lib:
44
+ level: warning
45
+ filter_mode: file
46
+
39
47
  - name: Test Pytest
40
48
  run: |
41
49
  pytest --junitxml=junit/test-results-${{ matrix.python-version }}.xml
@@ -0,0 +1,10 @@
1
+ {
2
+ "recommendations": [
3
+ "ms-python.flake8",
4
+ "github.vscode-github-actions",
5
+ "ms-python.vscode-pylance",
6
+ "ms-python.python",
7
+ "ms-python.debugpy",
8
+ "ms-python.black-formatter"
9
+ ]
10
+ }
@@ -2,11 +2,9 @@
2
2
  "python.testing.pytestEnabled": true,
3
3
  "python.testing.unittestEnabled": false,
4
4
  "editor.fontSize": 16,
5
- "python.formatting.provider": "none",
6
- "python.linting.flake8Enabled": true,
7
5
  "editor.formatOnPaste": true,
8
6
  "editor.formatOnSave": true,
9
7
  "[python]": {
10
8
  "editor.defaultFormatter": "ms-python.black-formatter"
11
9
  }
12
- }
10
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: artesian-sdk
3
- Version: 3.1.2.dev3
3
+ Version: 3.1.3
4
4
  Summary: Library provides read access to the Artesian API
5
5
  Author-email: ARK Lab <arklab@ark-energy.eu>
6
6
  Maintainer-email: ARK Lab <arklab@ark-energy.eu>
@@ -834,6 +834,29 @@ pageSize = 100
834
834
  res = mds.readCurveRange(100042422, page, pageSize, versionFrom="2016-12-20" , versionTo="2019-03-12")
835
835
  ```
836
836
 
837
+ ### Search the MarketData collection with faceted results
838
+
839
+ Using MarketDataService is possible to query and search the MarketData collection with faceted results. Supports paging, filtering and free text.
840
+
841
+ ```Python
842
+ from Artesian.MarketData import MarketDataService
843
+
844
+ mds = MarketDataService(cfg)
845
+
846
+ ```
847
+
848
+ To list MarketData curves
849
+
850
+ ```Python
851
+ page = 1
852
+ pageSize = 100
853
+ searchText = "Riconsegnato_"
854
+ filters = {"ProviderName": ["SNAM", "France"]}
855
+ sorts=["MarketDataId asc"]
856
+ doNotLoadAdditionalInfo=True
857
+ res = mds.searchFacet(page, pageSize, searchText, filters, sorts, doNotLoadAdditionalInfo)
858
+ ```
859
+
837
860
  ## Jupyter Support
838
861
 
839
862
  Artesian SDK uses asyncio internally, this causes a conflict with Jupyter. You can work around this issue by add the following at the beginning of the notebook.
@@ -780,6 +780,29 @@ pageSize = 100
780
780
  res = mds.readCurveRange(100042422, page, pageSize, versionFrom="2016-12-20" , versionTo="2019-03-12")
781
781
  ```
782
782
 
783
+ ### Search the MarketData collection with faceted results
784
+
785
+ Using MarketDataService is possible to query and search the MarketData collection with faceted results. Supports paging, filtering and free text.
786
+
787
+ ```Python
788
+ from Artesian.MarketData import MarketDataService
789
+
790
+ mds = MarketDataService(cfg)
791
+
792
+ ```
793
+
794
+ To list MarketData curves
795
+
796
+ ```Python
797
+ page = 1
798
+ pageSize = 100
799
+ searchText = "Riconsegnato_"
800
+ filters = {"ProviderName": ["SNAM", "France"]}
801
+ sorts=["MarketDataId asc"]
802
+ doNotLoadAdditionalInfo=True
803
+ res = mds.searchFacet(page, pageSize, searchText, filters, sorts, doNotLoadAdditionalInfo)
804
+ ```
805
+
783
806
  ## Jupyter Support
784
807
 
785
808
  Artesian SDK uses asyncio internally, this causes a conflict with Jupyter. You can work around this issue by add the following at the beginning of the notebook.
@@ -155,4 +155,11 @@ python_files = "Test*.py"
155
155
  testpaths = [
156
156
  "tests"
157
157
  ]
158
- addopts = "--doctest-modules --junitxml=junit/test-results.xml --cov=src --cov-report=xml --cov-report=html"
158
+ addopts = "--doctest-modules --junitxml=junit/test-results.xml --cov=src --cov-report=xml --cov-report=html"
159
+
160
+ [tool.pyright]
161
+ include = ["src"]
162
+ exclude = [
163
+ "**/node_modules",
164
+ "**/__pycache__"
165
+ ]
@@ -0,0 +1,28 @@
1
+ from Artesian import ArtesianConfig
2
+ from Artesian.MarketData import *
3
+
4
+ cfg = ArtesianConfig("https://arkive.artesian.cloud/tenantName/", "APIKey")
5
+ mkdservice = MarketDataService(cfg)
6
+
7
+ res = (
8
+ mkdservice.searchFacet(1, 1, "Riconsegnato_", filters={
9
+ "ProviderName": ["SNAM", "France"]
10
+ }
11
+ , sorts=["MarketDataId asc"], doNotLoadAdditionalInfo=False)
12
+ )
13
+
14
+ print(res.results)
15
+
16
+ res1 = (
17
+ mkdservice.searchFacet(1, 1, "Riconsegnato_")
18
+ )
19
+
20
+ print(res1.results)
21
+
22
+ res2 = (
23
+ mkdservice.searchFacet(1, 1, "Riconsegnato_", doNotLoadAdditionalInfo=True)
24
+ )
25
+
26
+ print(res2.results)
27
+
28
+ print("Test completed")
@@ -125,7 +125,7 @@ class ArtesianSdkOptimisticConcurrencyException(ArtesianSdkRemoteException):
125
125
  """
126
126
 
127
127
  def __init__(
128
- self: ArtesianSdkValidationException,
128
+ self: ArtesianSdkOptimisticConcurrencyException,
129
129
  method: str,
130
130
  url: str,
131
131
  statusCode: int,
@@ -15,7 +15,6 @@ from ._Enum.UnitType import UnitType
15
15
  from ._Enum.Zone import Zone
16
16
  import asyncio
17
17
  from urllib import parse
18
- import itertools
19
18
 
20
19
 
21
20
  class GMEPublicOfferQuery:
@@ -209,8 +208,8 @@ class GMEPublicOfferQuery:
209
208
  Returns:
210
209
  list of GMEPublicOffers.
211
210
  """
212
- urls = self.__buildRequest()
213
- return self._exec(urls)
211
+ url = self.__buildRequest()
212
+ return self._exec(url)
214
213
 
215
214
  async def executeAsync(self: GMEPublicOfferQuery) -> Any:
216
215
  """
@@ -219,13 +218,12 @@ class GMEPublicOfferQuery:
219
218
  Returns:
220
219
  Enumerable of TimeSerieRow Actual.
221
220
  """
222
- urls = self.__buildRequest()
223
- return await self._execAsync(urls)
221
+ url = self.__buildRequest()
222
+ return await self._execAsync(url)
224
223
 
225
224
  def __buildRequest(self: GMEPublicOfferQuery) -> str:
226
225
  self._validateQuery()
227
226
  qp = self._queryParameters
228
- urls = []
229
227
 
230
228
  url = "/{0}/{1}/{2}/{3}?_=1".format(
231
229
  self.__routePrefix,
@@ -281,9 +279,7 @@ class GMEPublicOfferQuery:
281
279
  enc = parse.quote_plus(baType)
282
280
  url = url + "&baType=" + enc
283
281
 
284
- urls.append(url)
285
-
286
- return urls
282
+ return url
287
283
 
288
284
  def __getScope(self: GMEPublicOfferQuery, scope: Scope) -> str:
289
285
  switcher = {
@@ -352,14 +348,19 @@ class GMEPublicOfferQuery:
352
348
  raise Exception("Not supported Market")
353
349
  return vr
354
350
 
355
- def __getPurpose(self: GMEPublicOfferQuery, purpose: Purpose) -> str:
351
+ def __getPurpose(self: GMEPublicOfferQuery, purpose: Purpose | None) -> str:
352
+ if purpose is None:
353
+ raise Exception("Not supported Purpose")
356
354
  switcher = {Purpose.BID: "BID", Purpose.OFF: "OFF"}
357
355
  vr = switcher.get(purpose, "Defpurp")
358
356
  if vr == "Defpurp":
359
357
  raise Exception("Not supported Purpose")
360
358
  return vr
361
359
 
362
- def __getStatus(self: GMEPublicOfferQuery, status: Status) -> str:
360
+ def __getStatus(self: GMEPublicOfferQuery, status: Status | None) -> str:
361
+ if status is None:
362
+ raise Exception("Not supported Status")
363
+
363
364
  switcher = {
364
365
  Status.ACC: "ACC",
365
366
  Status.INC: "INC",
@@ -433,27 +434,19 @@ class GMEPublicOfferQuery:
433
434
  subPath = f"{self.__toUrlParam(queryParamaters.extractionRangeConfig.date)}"
434
435
  return subPath
435
436
 
436
- def _buildExtractionStatus(self: GMEPublicOfferQuery, status: Status) -> str:
437
- subPath = f"{parse.quote_plus(status)}"
438
- return subPath
439
-
440
- def _buildExtractionPurpose(self: GMEPublicOfferQuery, purpose: Purpose) -> str:
441
- subPath = f"{parse.quote_plus(purpose)}"
442
- return subPath
443
-
444
- def _exec(self: GMEPublicOfferQuery, urls: List[str]) -> list:
437
+ def _exec(self: GMEPublicOfferQuery, url: str) -> Any:
445
438
  loop = get_event_loop()
446
- rr = loop.run_until_complete(self._execAsync(urls))
439
+ rr = loop.run_until_complete(self._execAsync(url))
447
440
  return rr
448
441
 
449
- async def _execAsync(self: GMEPublicOfferQuery, urls: List[str]) -> list:
442
+ async def _execAsync(self: GMEPublicOfferQuery, url: str) -> Any:
450
443
  with self.__client as c:
451
444
  res = await asyncio.gather(
452
- *[self.__executor.exec(c.exec, "GET", i, None) for i in urls]
445
+ *[self.__executor.exec(c.exec, "GET", url, None)]
453
446
  )
454
- return list(itertools.chain(*res))
447
+ return res[0]
455
448
 
456
- def __toUrlParam(self: GMEPublicOfferQuery, date: str) -> str:
449
+ def __toUrlParam(self: GMEPublicOfferQuery, date: str | None) -> str:
457
450
  return f"{date}"
458
451
 
459
452
  def _validateQuery(self: GMEPublicOfferQuery) -> None:
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
- from typing import Optional, cast
2
+ from typing import List, Optional, cast, Dict
3
3
  from .._ClientsExecutor.RequestExecutor import _RequestExecutor
4
4
  from .._ClientsExecutor.Client import _Client
5
5
  from ..ArtesianConfig import ArtesianConfig
6
6
  from ..ArtesianPolicyConfig import ArtesianPolicyConfig
7
7
  from ._Dto.PagedResult import PagedResultCurveRangeEntity
8
+ from ._Dto.ArtesianSearchResults import ArtesianSearchResults
8
9
  from ._Dto.MarketDataEntityInput import MarketDataEntityInput
9
10
  from ._Dto.MarketDataEntityOutput import MarketDataEntityOutput
10
11
  from ._Dto.UpsertData import UpsertData
@@ -113,6 +114,91 @@ class MarketDataService:
113
114
  )
114
115
  )
115
116
 
117
+ async def searchFacetAsync(
118
+ self: MarketDataService,
119
+ page: int,
120
+ pageSize: int,
121
+ searchText: str | None = None,
122
+ filters: Optional[Dict[str, List[str]]] = None,
123
+ sorts: Optional[List[str]] = None,
124
+ doNotLoadAdditionalInfo: bool = False,
125
+ ) -> ArtesianSearchResults:
126
+ """
127
+ Search the MarketData collection with faceted results.
128
+
129
+ Args:
130
+ searchText: SearchText parameter.
131
+ page: int of the page number (1-based).
132
+ pageSize: int of the pagesize.
133
+ filters: ArtesianSearchFilter containing the search params.
134
+ sorts: Sorts list.
135
+ doNotLoadAdditionalInfo: Skip loading up-to-date curve range and transform.
136
+
137
+ Returns:
138
+ ArtesianSearchResults entity (Async).
139
+ """
140
+ filtersList = None
141
+
142
+ if filters is not None:
143
+ filtersList = []
144
+ for key, values in filters.items():
145
+ for value in values:
146
+ filtersList.append(key + ":" + value)
147
+
148
+ url = "/marketdata/searchfacet"
149
+ params = {} # needed to avoid typing to detect dict[str,int] ...
150
+ params["page"] = page
151
+ params["pageSize"] = pageSize
152
+ params["searchText"] = searchText
153
+ if filters is not None:
154
+ params["filters"] = filtersList
155
+ if sorts is not None:
156
+ params["sorts"] = sorts
157
+ params["doNotLoadAdditionalInfo"] = doNotLoadAdditionalInfo
158
+
159
+ with self.__client as c:
160
+ res = await asyncio.gather(
161
+ *[
162
+ self.__executor.exec(
163
+ c.exec,
164
+ "GET",
165
+ url,
166
+ retcls=ArtesianSearchResults,
167
+ params=params,
168
+ )
169
+ ]
170
+ )
171
+ return cast(ArtesianSearchResults, res[0])
172
+
173
+ def searchFacet(
174
+ self: MarketDataService,
175
+ page: int,
176
+ pageSize: int,
177
+ searchText: Optional[str] = None,
178
+ filters: Optional[Dict[str, List[str]]] = None,
179
+ sorts: Optional[List[str]] = None,
180
+ doNotLoadAdditionalInfo: bool = False,
181
+ ) -> ArtesianSearchResults:
182
+ """
183
+ Search the MarketData collection with faceted results.
184
+
185
+ Args:
186
+ searchText: SearchText parameter.
187
+ page: int of the page number (1-based).
188
+ pageSize: int of the pagesize.
189
+ filters: ArtesianSearchFilter containing the search params.
190
+ sorts: Sorts list.
191
+ doNotLoadAdditionalInfo: Skip loading up-to-date curve range and transform.
192
+
193
+ Returns:
194
+ ArtesianSearchResults entity.
195
+ """
196
+ return _get_event_loop().run_until_complete(
197
+ self.searchFacetAsync(
198
+ page, pageSize, searchText, filters, sorts, doNotLoadAdditionalInfo
199
+ )
200
+ )
201
+
116
202
  async def readMarketDataRegistryByIdAsync(
117
203
  self: MarketDataService, id: int
118
204
  ) -> MarketDataEntityOutput:
@@ -0,0 +1,33 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+ from .._Enum import ArtesianMetadataFacetType
4
+
5
+
6
+ @dataclass
7
+ class ArtesianMetadataFacetCount:
8
+ """
9
+ Class for the ArtesianMetadataFacetCount Entity.
10
+
11
+ Attributes:
12
+ value: the value of the ArtesianMetadataFacet
13
+ count: the count of ArtesianMetadataFacet
14
+ """
15
+
16
+ value: Optional[str] = None
17
+ count: int = 0
18
+
19
+
20
+ @dataclass
21
+ class ArtesianMetadataFacet:
22
+ """
23
+ Class for the Facet Entity.
24
+
25
+ Attributes:
26
+ facetName: the name of the facet
27
+ facetType: the type of the facet
28
+ values: list of ArtesianMetadataFacetCount
29
+ """
30
+
31
+ facetName: Optional[str] = None
32
+ facetType: Optional[ArtesianMetadataFacetType] = None
33
+ values: Optional[List[ArtesianMetadataFacetCount]] = None
@@ -0,0 +1,20 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+ from .MarketDataEntityOutput import MarketDataEntityOutput
4
+ from .ArtesianMetadataFacet import ArtesianMetadataFacet
5
+
6
+
7
+ @dataclass
8
+ class ArtesianSearchResults:
9
+ """
10
+ Class for the Artesian Search Results.
11
+
12
+ Attributes:
13
+ results: list of MarketDataEntityOutput
14
+ facets: list of ArtesianMetadataFacet
15
+ countResults: the count of result
16
+ """
17
+
18
+ results: Optional[List[MarketDataEntityOutput]] = None
19
+ facets: Optional[List[ArtesianMetadataFacet]] = None
20
+ countResults: int = 0
@@ -2,6 +2,8 @@ from .MarketDataEntityInput import MarketDataEntityInput
2
2
  from .MarketDataEntityOutput import MarketDataEntityOutput
3
3
  from .CurveRangeEntity import CurveRangeEntity
4
4
  from .PagedResult import PagedResultCurveRangeEntity
5
+ from .ArtesianSearchResults import ArtesianSearchResults
6
+ from .ArtesianMetadataFacet import ArtesianMetadataFacet, ArtesianMetadataFacetCount
5
7
  from .MarketDataIdentifier import MarketDataIdentifier
6
8
  from .UpsertData import (
7
9
  AuctionBidValue,
@@ -22,4 +24,7 @@ __all__ = [
22
24
  BidAskValue.__name__,
23
25
  MarketAssessmentValue.__name__,
24
26
  UpsertData.__name__,
27
+ ArtesianSearchResults.__name__,
28
+ ArtesianMetadataFacet.__name__,
29
+ ArtesianMetadataFacetCount.__name__,
25
30
  ] # type: ignore
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ArtesianMetadataFacetType(Enum):
5
+ Property = 0
6
+ Tag = 1
@@ -1,9 +1,11 @@
1
1
  from .AggregationRule import AggregationRule
2
2
  from ...Granularity import Granularity
3
3
  from .MarketDataType import MarketDataType
4
+ from .ArtesianMetadataFacetType import ArtesianMetadataFacetType
4
5
 
5
6
  __all__ = [
6
7
  AggregationRule.__name__,
7
8
  Granularity.__name__,
8
9
  MarketDataType.__name__,
10
+ ArtesianMetadataFacetType.__name__,
9
11
  ] # type: ignore
@@ -2,6 +2,8 @@ from .MarketDataService import MarketDataService
2
2
  from ._Enum.AggregationRule import AggregationRule
3
3
  from ..Granularity import Granularity
4
4
  from ._Enum.MarketDataType import MarketDataType
5
+ from ._Enum.ArtesianMetadataFacetType import ArtesianMetadataFacetType
6
+
5
7
  from ._Dto import (
6
8
  AuctionBids,
7
9
  AuctionBidValue,
@@ -13,6 +15,9 @@ from ._Dto import (
13
15
  MarketDataIdentifier,
14
16
  UpsertData,
15
17
  PagedResultCurveRangeEntity,
18
+ ArtesianSearchResults,
19
+ ArtesianMetadataFacet,
20
+ ArtesianMetadataFacetCount,
16
21
  )
17
22
 
18
23
  __all__ = [
@@ -30,4 +35,8 @@ __all__ = [
30
35
  MarketDataEntityOutput.__name__,
31
36
  MarketDataIdentifier.__name__,
32
37
  UpsertData.__name__,
38
+ ArtesianSearchResults.__name__,
39
+ ArtesianMetadataFacet.__name__,
40
+ ArtesianMetadataFacetCount.__name__,
41
+ ArtesianMetadataFacetType.__name__,
33
42
  ] # type: ignore
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
  import copy
3
- from typing import List
3
+ from typing import List, TypeVar
4
+
5
+ from ._QueryParameters.QueryParameters import _QueryParameters
4
6
  from ._QueryParameters.ActualQueryParameters import ActualQueryParameters
5
7
  from ._QueryParameters.VersionedQueryParameters import VersionedQueryParameters
6
8
  from ._QueryParameters.AuctionQueryParameters import AuctionQueryParameters
@@ -8,6 +10,9 @@ from ._QueryParameters.MasQueryParameters import MasQueryParameters
8
10
  from ._QueryParameters.BidAskQueryParameters import BidAskQueryParameters
9
11
 
10
12
 
13
+ T = TypeVar("T", bound=_QueryParameters)
14
+
15
+
11
16
  class DefaultPartitionStrategy:
12
17
  """Class for the default strategy to partition Query Parameters."""
13
18
 
@@ -89,9 +94,9 @@ class DefaultPartitionStrategy:
89
94
  return self._tsPartitionStrategy(bidAskQueryParameters)
90
95
 
91
96
  def _tsPartitionStrategy(
92
- self: DefaultPartitionStrategy, Parameters: List[MasQueryParameters]
93
- ) -> List[MasQueryParameters]:
94
- res: List[MasQueryParameters] = []
97
+ self: DefaultPartitionStrategy, Parameters: List[T]
98
+ ) -> List[T]:
99
+ res: List[T] = []
95
100
  for param in Parameters:
96
101
  if param.ids is None:
97
102
  res.append(param)
@@ -172,7 +172,7 @@ class _Query:
172
172
  )
173
173
  return list(itertools.chain(*res))
174
174
 
175
- def __toUrlParam(self: _Query, start: str, end: str) -> str:
175
+ def __toUrlParam(self: _Query, start: str | None, end: str | None) -> str:
176
176
  return f"{start}/{end}"
177
177
 
178
178
  def _validateQuery(self: _Query) -> None:
@@ -40,7 +40,7 @@ class _FillCustomTimeserieStrategy(_FillStrategy):
40
40
  return f"fillerK=CustomValue&fillerDV={self.val}"
41
41
 
42
42
 
43
- def toQueryParams(vals: List[List[str]]) -> str:
43
+ def toQueryParams(vals: List[List[str | float | int | None]]) -> str:
44
44
  filtered = filter(lambda x: x[1], vals)
45
45
  stringVals = map(lambda x: [x[0], str(x[1])], filtered)
46
46
  joinedEqual = map(lambda x: "=".join(x), stringVals)
@@ -57,7 +57,7 @@ def __artesianDictDeserializer(
57
57
  obj: list, cls: type, *args: Any, **kwargs: Any
58
58
  ) -> object:
59
59
  key, value = get_args(cls)
60
- result: Dict[key, value] = {
60
+ result: Dict[key, value] = { # type: ignore
61
61
  jsons.load(item["Key"], key, *args, **kwargs): jsons.load(
62
62
  item["Value"], value, *args, **kwargs
63
63
  )
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.1.2.dev3'
16
- __version_tuple__ = version_tuple = (3, 1, 2, 'dev3')
15
+ __version__ = version = '3.1.3'
16
+ __version_tuple__ = version_tuple = (3, 1, 3)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: artesian-sdk
3
- Version: 3.1.2.dev3
3
+ Version: 3.1.3
4
4
  Summary: Library provides read access to the Artesian API
5
5
  Author-email: ARK Lab <arklab@ark-energy.eu>
6
6
  Maintainer-email: ARK Lab <arklab@ark-energy.eu>
@@ -834,6 +834,29 @@ pageSize = 100
834
834
  res = mds.readCurveRange(100042422, page, pageSize, versionFrom="2016-12-20" , versionTo="2019-03-12")
835
835
  ```
836
836
 
837
+ ### Search the MarketData collection with faceted results
838
+
839
+ Using MarketDataService is possible to query and search the MarketData collection with faceted results. Supports paging, filtering and free text.
840
+
841
+ ```Python
842
+ from Artesian.MarketData import MarketDataService
843
+
844
+ mds = MarketDataService(cfg)
845
+
846
+ ```
847
+
848
+ To list MarketData curves
849
+
850
+ ```Python
851
+ page = 1
852
+ pageSize = 100
853
+ searchText = "Riconsegnato_"
854
+ filters = {"ProviderName": ["SNAM", "France"]}
855
+ sorts=["MarketDataId asc"]
856
+ doNotLoadAdditionalInfo=True
857
+ res = mds.searchFacet(page, pageSize, searchText, filters, sorts, doNotLoadAdditionalInfo)
858
+ ```
859
+
837
860
  ## Jupyter Support
838
861
 
839
862
  Artesian SDK uses asyncio internally, this causes a conflict with Jupyter. You can work around this issue by add the following at the beginning of the notebook.
@@ -7,6 +7,7 @@ pyproject.toml
7
7
  .github/dependabot.yml
8
8
  .github/workflows/dependency-review.yaml
9
9
  .github/workflows/python-tests.yml
10
+ .vscode/extensions.json
10
11
  .vscode/launch.json
11
12
  .vscode/settings.json
12
13
  samples/TestActual.py
@@ -15,6 +16,7 @@ samples/TestBidAsk.py
15
16
  samples/TestGMEOffers.py
16
17
  samples/TestMarketDataService.py
17
18
  samples/TestMas.py
19
+ samples/TestSearchFacet.py
18
20
  samples/TestVersioned.py
19
21
  samples/TestWriteDataAndQueryActual.py
20
22
  samples/TestWriteDataAndQueryAuction.py
@@ -43,6 +45,8 @@ src/Artesian/GMEPublicOffers/_Enum/Zone.py
43
45
  src/Artesian/GMEPublicOffers/_Enum/__init__.py
44
46
  src/Artesian/MarketData/MarketDataService.py
45
47
  src/Artesian/MarketData/__init__.py
48
+ src/Artesian/MarketData/_Dto/ArtesianMetadataFacet.py
49
+ src/Artesian/MarketData/_Dto/ArtesianSearchResults.py
46
50
  src/Artesian/MarketData/_Dto/CurveRangeEntity.py
47
51
  src/Artesian/MarketData/_Dto/MarketDataEntityInput.py
48
52
  src/Artesian/MarketData/_Dto/MarketDataEntityOutput.py
@@ -51,6 +55,7 @@ src/Artesian/MarketData/_Dto/PagedResult.py
51
55
  src/Artesian/MarketData/_Dto/UpsertData.py
52
56
  src/Artesian/MarketData/_Dto/__init__.py
53
57
  src/Artesian/MarketData/_Enum/AggregationRule.py
58
+ src/Artesian/MarketData/_Enum/ArtesianMetadataFacetType.py
54
59
  src/Artesian/MarketData/_Enum/MarketDataType.py
55
60
  src/Artesian/MarketData/_Enum/__init__.py
56
61
  src/Artesian/Query/ActualQuery.py
@@ -9,6 +9,8 @@ from Artesian.GMEPublicOffers import (
9
9
  from . import helpers
10
10
  import unittest
11
11
  from urllib.parse import unquote
12
+ from Artesian._ClientsExecutor.ArtesianJsonSerializer import artesianJsonSerialize
13
+ import responses
12
14
 
13
15
  cfg = ArtesianConfig("https://arkive.artesian.cloud/tenantName/", "APIKey")
14
16
 
@@ -16,6 +18,20 @@ qs = GMEPublicOfferService(cfg)
16
18
 
17
19
 
18
20
  class TestGMEPO(unittest.TestCase):
21
+
22
+ def setUp(self) -> None:
23
+ self.__baseurl = "https://arkive.artesian.cloud/tenantName//"
24
+ self.__sampleOutput = dict(
25
+ Page=1,
26
+ PageSize=10,
27
+ Count=0,
28
+ IsCountPartial=False,
29
+ Data=[[]],
30
+ )
31
+ self.__serializedOutput = artesianJsonSerialize(self.__sampleOutput)
32
+
33
+ return super().setUp()
34
+
19
35
  @helpers.TrackGMEPORequests
20
36
  def test_Market(self, requests):
21
37
  url = (
@@ -87,3 +103,24 @@ class TestGMEPO(unittest.TestCase):
87
103
  query = requests.getQs()
88
104
  self.assertEqual(query["page"], "1")
89
105
  self.assertEqual(query["pageSize"], "100")
106
+
107
+ def test_checkreturnedPayload(self):
108
+ with responses.RequestsMock() as rsps:
109
+ rsps.add(
110
+ "GET",
111
+ self.__baseurl
112
+ + "gmepublicoffer/v2.0/extract/2024-01-21/BID/ACC?_=1&page=1&pageSize=10",
113
+ json=self.__sampleOutput,
114
+ status=200,
115
+ )
116
+
117
+ output = (
118
+ qs.createQuery()
119
+ .forDate("2024-01-21")
120
+ .forStatus(Status.ACC)
121
+ .forPurpose(Purpose.BID)
122
+ .withPagination(1, 10)
123
+ .execute()
124
+ )
125
+
126
+ self.assertEqual(output, self.__sampleOutput)
@@ -16,6 +16,7 @@ class TestMarketDataServiceMarketData(unittest.IsolatedAsyncioTestCase):
16
16
  originalGranularity=Granularity.Day,
17
17
  type=MarketDataType.ActualTimeSerie,
18
18
  originalTimezone="CET",
19
+ tags={"PythonTag": ["PythonTagValue1", "PythonTagValue2"]}
19
20
  )
20
21
  self.__serializedOutput = artesianJsonSerialize(self.__sampleOutput)
21
22
  self.__sampleInput = MarketDataEntityInput(
@@ -35,6 +36,23 @@ class TestMarketDataServiceMarketData(unittest.IsolatedAsyncioTestCase):
35
36
  self.__curveRangeSerializedOutput = artesianJsonSerialize(
36
37
  self.__curveRangeOutput
37
38
  )
39
+ self.__artesianMetadataFacetCount = ArtesianMetadataFacetCount(
40
+ value="TestValue",
41
+ count=1
42
+ )
43
+ self.__artesianMetadataFacet = ArtesianMetadataFacet(
44
+ facetName="TestFacet",
45
+ facetType=ArtesianMetadataFacetType.Tag,
46
+ values=[self.__artesianMetadataFacetCount],
47
+ )
48
+ self.__artesianSearchResults = ArtesianSearchResults(
49
+ results=[self.__sampleOutput],
50
+ facets=[self.__artesianMetadataFacet],
51
+ countResults=1,
52
+ )
53
+ self.__artesianSearchResultsSerializedOutput = artesianJsonSerialize(
54
+ self.__artesianSearchResults
55
+ )
38
56
 
39
57
  return super().setUp()
40
58
 
@@ -171,3 +189,39 @@ class TestMarketDataServiceMarketData(unittest.IsolatedAsyncioTestCase):
171
189
  params["versionTo"],
172
190
  )
173
191
  self.assertEqual(output, self.__curveRangeOutput)
192
+
193
+ async def test_searchFacetAsync(self):
194
+ with responses.RequestsMock() as rsps:
195
+ params = {
196
+ "page": "1",
197
+ "pageSize": "2",
198
+ "searchText": "arktest +curve",
199
+ "filters": {"Market": ["Italy", "France"]},
200
+ "sorts": ["FacetName", "FacetType"],
201
+ "doNotLoadAdditionalInfo": True,
202
+ }
203
+ paramsToMatch = {
204
+ "page": "1",
205
+ "pageSize": "2",
206
+ "searchText": "arktest +curve",
207
+ "filters": ["Market:Italy", "Market:France"],
208
+ "sorts": ["FacetName", "FacetType"],
209
+ "doNotLoadAdditionalInfo": True,
210
+ }
211
+
212
+ rsps.add(
213
+ "GET",
214
+ self.__baseurl + "/marketdata/searchfacet",
215
+ match=[responses.matchers.query_param_matcher(paramsToMatch)],
216
+ json=self.__artesianSearchResultsSerializedOutput,
217
+ status=200,
218
+ )
219
+ output = await self.__service.searchFacetAsync(
220
+ int(params["page"]),
221
+ int(params["pageSize"]),
222
+ str(params["searchText"]),
223
+ params["filters"],
224
+ params["sorts"],
225
+ bool(params["doNotLoadAdditionalInfo"]),
226
+ )
227
+ self.assertEqual(output, self.__artesianSearchResults)
@@ -15,7 +15,7 @@ class Qs:
15
15
  return dict(
16
16
  map(
17
17
  lambda x: x.split("="),
18
- unquote(self._mock.call_args.args[0][0]).split("?")[1].split("&"),
18
+ unquote(urlparse(self._mock.call_args.args[0][0]).query).split("&"),
19
19
  )
20
20
  )
21
21
 
@@ -23,6 +23,23 @@ class Qs:
23
23
  return urlparse(self._mock.call_args.args[0][0]).path
24
24
 
25
25
 
26
+ class QsPO:
27
+
28
+ def __init__(self: QsPO, mock: Mock) -> None:
29
+ self._mock = mock
30
+
31
+ def getQs(self: QsPO) -> Dict[str, str]:
32
+ return dict(
33
+ map(
34
+ lambda x: x.split("="),
35
+ unquote(urlparse(self._mock.call_args.args[0]).query).split("&"),
36
+ )
37
+ )
38
+
39
+ def getPath(self: Qs) -> str:
40
+ return urlparse(self._mock.call_args.args[0]).path
41
+
42
+
26
43
  def TrackRequests(func: Callable) -> Callable[[Any, Qs], None]:
27
44
  @patch.object(_Query._Query, "_exec")
28
45
  def wrapper(self: Any, mock: Mock) -> None:
@@ -34,6 +51,6 @@ def TrackRequests(func: Callable) -> Callable[[Any, Qs], None]:
34
51
  def TrackGMEPORequests(func: Callable) -> Callable[[Any, Qs], None]:
35
52
  @patch.object(_GMEPO.GMEPublicOfferQuery, "_exec")
36
53
  def wrapper(self: Any, mock: Mock) -> None:
37
- func(self, Qs(mock))
54
+ func(self, QsPO(mock))
38
55
 
39
56
  return wrapper
File without changes
File without changes