poelis-sdk 0.3.1__py3-none-any.whl → 0.3.3__py3-none-any.whl
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.
Potentially problematic release.
This version of poelis-sdk might be problematic. Click here for more details.
- poelis_sdk/browser.py +131 -32
- poelis_sdk/models.py +104 -1
- poelis_sdk/search.py +1 -1
- {poelis_sdk-0.3.1.dist-info → poelis_sdk-0.3.3.dist-info}/METADATA +1 -1
- {poelis_sdk-0.3.1.dist-info → poelis_sdk-0.3.3.dist-info}/RECORD +7 -7
- {poelis_sdk-0.3.1.dist-info → poelis_sdk-0.3.3.dist-info}/WHEEL +0 -0
- {poelis_sdk-0.3.1.dist-info → poelis_sdk-0.3.3.dist-info}/licenses/LICENSE +0 -0
poelis_sdk/browser.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
from types import MethodType
|
|
5
5
|
import re
|
|
6
|
+
import time
|
|
6
7
|
|
|
7
8
|
from .org_validation import get_organization_context_message
|
|
8
9
|
|
|
@@ -26,6 +27,10 @@ class _Node:
|
|
|
26
27
|
self._name = name
|
|
27
28
|
self._children_cache: Dict[str, "_Node"] = {}
|
|
28
29
|
self._props_cache: Optional[List[Dict[str, Any]]] = None
|
|
30
|
+
# Performance optimization: cache metadata with TTL
|
|
31
|
+
self._children_loaded_at: Optional[float] = None
|
|
32
|
+
self._props_loaded_at: Optional[float] = None
|
|
33
|
+
self._cache_ttl: float = 30.0 # 30 seconds cache TTL
|
|
29
34
|
|
|
30
35
|
def __repr__(self) -> str: # pragma: no cover - notebook UX
|
|
31
36
|
path = []
|
|
@@ -36,8 +41,9 @@ class _Node:
|
|
|
36
41
|
return f"<{self._level}:{'.'.join(reversed(path)) or '*'}>"
|
|
37
42
|
|
|
38
43
|
def __dir__(self) -> List[str]: # pragma: no cover - notebook UX
|
|
39
|
-
#
|
|
40
|
-
self.
|
|
44
|
+
# Performance optimization: only load children if cache is stale or empty
|
|
45
|
+
if self._is_children_cache_stale():
|
|
46
|
+
self._load_children()
|
|
41
47
|
keys = list(self._children_cache.keys())
|
|
42
48
|
if self._level == "item":
|
|
43
49
|
# Include property names directly on item for suggestions
|
|
@@ -49,11 +55,30 @@ class _Node:
|
|
|
49
55
|
def _refresh(self) -> "_Node":
|
|
50
56
|
self._children_cache.clear()
|
|
51
57
|
self._props_cache = None
|
|
58
|
+
self._children_loaded_at = None
|
|
59
|
+
self._props_loaded_at = None
|
|
52
60
|
return self
|
|
53
61
|
|
|
62
|
+
def _is_children_cache_stale(self) -> bool:
|
|
63
|
+
"""Check if children cache is stale and needs refresh."""
|
|
64
|
+
if not self._children_cache:
|
|
65
|
+
return True
|
|
66
|
+
if self._children_loaded_at is None:
|
|
67
|
+
return True
|
|
68
|
+
return time.time() - self._children_loaded_at > self._cache_ttl
|
|
69
|
+
|
|
70
|
+
def _is_props_cache_stale(self) -> bool:
|
|
71
|
+
"""Check if properties cache is stale and needs refresh."""
|
|
72
|
+
if self._props_cache is None:
|
|
73
|
+
return True
|
|
74
|
+
if self._props_loaded_at is None:
|
|
75
|
+
return True
|
|
76
|
+
return time.time() - self._props_loaded_at > self._cache_ttl
|
|
77
|
+
|
|
54
78
|
def _names(self) -> List[str]:
|
|
55
79
|
"""Return display names of children at this level (internal)."""
|
|
56
|
-
self.
|
|
80
|
+
if self._is_children_cache_stale():
|
|
81
|
+
self._load_children()
|
|
57
82
|
return [child._name or "" for child in self._children_cache.values()]
|
|
58
83
|
|
|
59
84
|
def names(self) -> List[str]:
|
|
@@ -65,7 +90,8 @@ class _Node:
|
|
|
65
90
|
|
|
66
91
|
Only child keys are returned; for item level, property keys are also included.
|
|
67
92
|
"""
|
|
68
|
-
self.
|
|
93
|
+
if self._is_children_cache_stale():
|
|
94
|
+
self._load_children()
|
|
69
95
|
suggestions: List[str] = list(self._children_cache.keys())
|
|
70
96
|
if self._level == "item":
|
|
71
97
|
suggestions.extend(list(self._props_key_map().keys()))
|
|
@@ -78,7 +104,8 @@ class _Node:
|
|
|
78
104
|
raise AttributeError("props")
|
|
79
105
|
return _PropsNode(self)
|
|
80
106
|
if attr not in self._children_cache:
|
|
81
|
-
self.
|
|
107
|
+
if self._is_children_cache_stale():
|
|
108
|
+
self._load_children()
|
|
82
109
|
if attr in self._children_cache:
|
|
83
110
|
return self._children_cache[attr]
|
|
84
111
|
# Expose properties as direct attributes on item level
|
|
@@ -93,7 +120,8 @@ class _Node:
|
|
|
93
120
|
|
|
94
121
|
This enables names with spaces or symbols: browser["Workspace Name"].
|
|
95
122
|
"""
|
|
96
|
-
self.
|
|
123
|
+
if self._is_children_cache_stale():
|
|
124
|
+
self._load_children()
|
|
97
125
|
if key in self._children_cache:
|
|
98
126
|
return self._children_cache[key]
|
|
99
127
|
for child in self._children_cache.values():
|
|
@@ -105,43 +133,84 @@ class _Node:
|
|
|
105
133
|
raise KeyError(key)
|
|
106
134
|
|
|
107
135
|
def _properties(self) -> List[Dict[str, Any]]:
|
|
108
|
-
if self.
|
|
109
|
-
return self._props_cache
|
|
136
|
+
if not self._is_props_cache_stale():
|
|
137
|
+
return self._props_cache or []
|
|
110
138
|
if self._level != "item":
|
|
111
139
|
self._props_cache = []
|
|
140
|
+
self._props_loaded_at = time.time()
|
|
112
141
|
return self._props_cache
|
|
113
142
|
# Try direct properties(itemId: ...) first; fallback to searchProperties
|
|
114
|
-
|
|
143
|
+
# Attempt 1: query with parsedValue support
|
|
144
|
+
q_parsed = (
|
|
115
145
|
"query($iid: ID!) {\n"
|
|
116
146
|
" properties(itemId: $iid) {\n"
|
|
117
147
|
" __typename\n"
|
|
118
|
-
" ... on NumericProperty {
|
|
119
|
-
" ... on TextProperty { value }\n"
|
|
148
|
+
" ... on NumericProperty { category value parsedValue }\n"
|
|
149
|
+
" ... on TextProperty { value parsedValue }\n"
|
|
120
150
|
" ... on DateProperty { value }\n"
|
|
121
151
|
" }\n"
|
|
122
152
|
"}"
|
|
123
153
|
)
|
|
124
154
|
try:
|
|
125
|
-
r = self._client._transport.graphql(
|
|
155
|
+
r = self._client._transport.graphql(q_parsed, {"iid": self._id})
|
|
126
156
|
r.raise_for_status()
|
|
127
157
|
data = r.json()
|
|
128
158
|
if "errors" in data:
|
|
129
|
-
raise RuntimeError(data["errors"]) #
|
|
159
|
+
raise RuntimeError(data["errors"]) # try value-only shape
|
|
130
160
|
self._props_cache = data.get("data", {}).get("properties", []) or []
|
|
161
|
+
self._props_loaded_at = time.time()
|
|
131
162
|
except Exception:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
"
|
|
135
|
-
"
|
|
163
|
+
# Attempt 2: value-only, legacy compatible
|
|
164
|
+
q_value_only = (
|
|
165
|
+
"query($iid: ID!) {\n"
|
|
166
|
+
" properties(itemId: $iid) {\n"
|
|
167
|
+
" __typename\n"
|
|
168
|
+
" ... on NumericProperty { category value }\n"
|
|
169
|
+
" ... on TextProperty { value }\n"
|
|
170
|
+
" ... on DateProperty { value }\n"
|
|
136
171
|
" }\n"
|
|
137
172
|
"}"
|
|
138
173
|
)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
174
|
+
try:
|
|
175
|
+
r = self._client._transport.graphql(q_value_only, {"iid": self._id})
|
|
176
|
+
r.raise_for_status()
|
|
177
|
+
data = r.json()
|
|
178
|
+
if "errors" in data:
|
|
179
|
+
raise RuntimeError(data["errors"]) # trigger fallback to search
|
|
180
|
+
self._props_cache = data.get("data", {}).get("properties", []) or []
|
|
181
|
+
self._props_loaded_at = time.time()
|
|
182
|
+
except Exception:
|
|
183
|
+
# Fallback to searchProperties
|
|
184
|
+
q2_parsed = (
|
|
185
|
+
"query($iid: ID!, $limit: Int!, $offset: Int!) {\n"
|
|
186
|
+
" searchProperties(q: \"*\", itemId: $iid, limit: $limit, offset: $offset) {\n"
|
|
187
|
+
" hits { id workspaceId productId itemId propertyType name category value parsedValue owner }\n"
|
|
188
|
+
" }\n"
|
|
189
|
+
"}"
|
|
190
|
+
)
|
|
191
|
+
try:
|
|
192
|
+
r2 = self._client._transport.graphql(q2_parsed, {"iid": self._id, "limit": 100, "offset": 0})
|
|
193
|
+
r2.raise_for_status()
|
|
194
|
+
data2 = r2.json()
|
|
195
|
+
if "errors" in data2:
|
|
196
|
+
raise RuntimeError(data2["errors"]) # try minimal
|
|
197
|
+
self._props_cache = data2.get("data", {}).get("searchProperties", {}).get("hits", []) or []
|
|
198
|
+
self._props_loaded_at = time.time()
|
|
199
|
+
except Exception:
|
|
200
|
+
q2_min = (
|
|
201
|
+
"query($iid: ID!, $limit: Int!, $offset: Int!) {\n"
|
|
202
|
+
" searchProperties(q: \"*\", itemId: $iid, limit: $limit, offset: $offset) {\n"
|
|
203
|
+
" hits { id workspaceId productId itemId propertyType name category value owner }\n"
|
|
204
|
+
" }\n"
|
|
205
|
+
"}"
|
|
206
|
+
)
|
|
207
|
+
r3 = self._client._transport.graphql(q2_min, {"iid": self._id, "limit": 100, "offset": 0})
|
|
208
|
+
r3.raise_for_status()
|
|
209
|
+
data3 = r3.json()
|
|
210
|
+
if "errors" in data3:
|
|
211
|
+
raise RuntimeError(data3["errors"]) # propagate
|
|
212
|
+
self._props_cache = data3.get("data", {}).get("searchProperties", {}).get("hits", []) or []
|
|
213
|
+
self._props_loaded_at = time.time()
|
|
145
214
|
return self._props_cache
|
|
146
215
|
|
|
147
216
|
def _props_key_map(self) -> Dict[str, Dict[str, Any]]:
|
|
@@ -172,20 +241,26 @@ class _Node:
|
|
|
172
241
|
for w in rows:
|
|
173
242
|
display = w.get("name") or str(w.get("id"))
|
|
174
243
|
nm = _safe_key(display)
|
|
175
|
-
|
|
244
|
+
child = _Node(self._client, "workspace", self, w["id"], display)
|
|
245
|
+
child._cache_ttl = self._cache_ttl
|
|
246
|
+
self._children_cache[nm] = child
|
|
176
247
|
elif self._level == "workspace":
|
|
177
248
|
page = self._client.products.list_by_workspace(workspace_id=self._id, limit=200, offset=0)
|
|
178
249
|
for p in page.data:
|
|
179
250
|
display = p.name or str(p.id)
|
|
180
251
|
nm = _safe_key(display)
|
|
181
|
-
|
|
252
|
+
child = _Node(self._client, "product", self, p.id, display)
|
|
253
|
+
child._cache_ttl = self._cache_ttl
|
|
254
|
+
self._children_cache[nm] = child
|
|
182
255
|
elif self._level == "product":
|
|
183
256
|
rows = self._client.items.list_by_product(product_id=self._id, limit=1000, offset=0)
|
|
184
257
|
for it in rows:
|
|
185
258
|
if it.get("parentId") is None:
|
|
186
259
|
display = it.get("name") or str(it["id"])
|
|
187
260
|
nm = _safe_key(display)
|
|
188
|
-
|
|
261
|
+
child = _Node(self._client, "item", self, it["id"], display)
|
|
262
|
+
child._cache_ttl = self._cache_ttl
|
|
263
|
+
self._children_cache[nm] = child
|
|
189
264
|
elif self._level == "item":
|
|
190
265
|
# Fetch children items by parent; derive productId from ancestor product
|
|
191
266
|
anc = self
|
|
@@ -214,14 +289,27 @@ class _Node:
|
|
|
214
289
|
continue
|
|
215
290
|
display = it2.get("name") or str(it2["id"])
|
|
216
291
|
nm = _safe_key(display)
|
|
217
|
-
|
|
292
|
+
child = _Node(self._client, "item", self, it2["id"], display)
|
|
293
|
+
child._cache_ttl = self._cache_ttl
|
|
294
|
+
self._children_cache[nm] = child
|
|
295
|
+
|
|
296
|
+
# Mark cache as fresh
|
|
297
|
+
self._children_loaded_at = time.time()
|
|
218
298
|
|
|
219
299
|
|
|
220
300
|
class Browser:
|
|
221
301
|
"""Public browser entrypoint."""
|
|
222
302
|
|
|
223
|
-
def __init__(self, client: Any) -> None:
|
|
303
|
+
def __init__(self, client: Any, cache_ttl: float = 30.0) -> None:
|
|
304
|
+
"""Initialize browser with optional cache TTL.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
client: PoelisClient instance
|
|
308
|
+
cache_ttl: Cache time-to-live in seconds (default: 30)
|
|
309
|
+
"""
|
|
224
310
|
self._root = _Node(client, "root", None, None, None)
|
|
311
|
+
# Set cache TTL for all nodes
|
|
312
|
+
self._root._cache_ttl = cache_ttl
|
|
225
313
|
# Best-effort: auto-enable curated completion in interactive shells
|
|
226
314
|
global _AUTO_COMPLETER_INSTALLED
|
|
227
315
|
if not _AUTO_COMPLETER_INSTALLED:
|
|
@@ -245,8 +333,9 @@ class Browser:
|
|
|
245
333
|
return self._root[key]
|
|
246
334
|
|
|
247
335
|
def __dir__(self) -> list[str]: # pragma: no cover - notebook UX
|
|
248
|
-
#
|
|
249
|
-
self._root.
|
|
336
|
+
# Performance optimization: only load children if cache is stale or empty
|
|
337
|
+
if self._root._is_children_cache_stale():
|
|
338
|
+
self._root._load_children()
|
|
250
339
|
return sorted([*self._root._children_cache.keys()])
|
|
251
340
|
|
|
252
341
|
def _names(self) -> List[str]:
|
|
@@ -288,13 +377,18 @@ class _PropsNode:
|
|
|
288
377
|
self._item = item_node
|
|
289
378
|
self._children_cache: Dict[str, _PropWrapper] = {}
|
|
290
379
|
self._names: List[str] = []
|
|
380
|
+
self._loaded_at: Optional[float] = None
|
|
381
|
+
self._cache_ttl: float = item_node._cache_ttl # Inherit cache TTL from parent node
|
|
291
382
|
|
|
292
383
|
def __repr__(self) -> str: # pragma: no cover - notebook UX
|
|
293
384
|
return f"<props of {self._item.name or self._item.id}>"
|
|
294
385
|
|
|
295
386
|
def _ensure_loaded(self) -> None:
|
|
296
|
-
if
|
|
297
|
-
|
|
387
|
+
# Performance optimization: only load if cache is stale or empty
|
|
388
|
+
if self._children_cache and self._loaded_at is not None:
|
|
389
|
+
if time.time() - self._loaded_at <= self._cache_ttl:
|
|
390
|
+
return
|
|
391
|
+
|
|
298
392
|
props = self._item._properties()
|
|
299
393
|
used_names: Dict[str, int] = {}
|
|
300
394
|
names_list = []
|
|
@@ -313,6 +407,7 @@ class _PropsNode:
|
|
|
313
407
|
self._children_cache[safe] = _PropWrapper(pr)
|
|
314
408
|
names_list.append(display)
|
|
315
409
|
self._names = names_list
|
|
410
|
+
self._loaded_at = time.time()
|
|
316
411
|
|
|
317
412
|
def __dir__(self) -> List[str]: # pragma: no cover - notebook UX
|
|
318
413
|
self._ensure_loaded()
|
|
@@ -362,6 +457,10 @@ class _PropWrapper:
|
|
|
362
457
|
@property
|
|
363
458
|
def value(self) -> Any: # type: ignore[override]
|
|
364
459
|
p = self._raw
|
|
460
|
+
# Use parsedValue if available (new backend feature)
|
|
461
|
+
if "parsedValue" in p:
|
|
462
|
+
return p["parsedValue"]
|
|
463
|
+
# Fallback to legacy parsing logic for backward compatibility
|
|
365
464
|
# searchProperties shape
|
|
366
465
|
if "numericValue" in p and p.get("numericValue") is not None:
|
|
367
466
|
return p["numericValue"]
|
poelis_sdk/models.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Optional, Any, Union, List
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
@@ -25,3 +25,106 @@ class PaginatedProducts(BaseModel):
|
|
|
25
25
|
offset: int
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
class PropertyValue(BaseModel):
|
|
29
|
+
"""Base class for property values with typed access."""
|
|
30
|
+
|
|
31
|
+
raw_value: str = Field(alias="value")
|
|
32
|
+
parsed_value: Optional[Any] = Field(alias="parsedValue", default=None)
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def value(self) -> Any:
|
|
36
|
+
"""Get the properly typed value, falling back to raw string if parsing failed."""
|
|
37
|
+
return self.parsed_value if self.parsed_value is not None else self.raw_value
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NumericProperty(BaseModel):
|
|
41
|
+
"""Numeric property representation."""
|
|
42
|
+
|
|
43
|
+
id: str = Field(min_length=1)
|
|
44
|
+
item_id: str = Field(alias="itemId", min_length=1)
|
|
45
|
+
position: float
|
|
46
|
+
name: str = Field(min_length=1)
|
|
47
|
+
value: str
|
|
48
|
+
category: str
|
|
49
|
+
display_unit: Optional[str] = Field(alias="displayUnit", default=None)
|
|
50
|
+
owner: str = Field(min_length=1)
|
|
51
|
+
type: str = Field(min_length=1)
|
|
52
|
+
parsed_value: Optional[Union[int, float, List[Any], str]] = Field(alias="parsedValue", default=None)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def typed_value(self) -> Union[int, float, List[Any], str]:
|
|
56
|
+
"""Get the properly typed value, falling back to raw string if parsing failed."""
|
|
57
|
+
return self.parsed_value if self.parsed_value is not None else self.value
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class TextProperty(BaseModel):
|
|
61
|
+
"""Text property representation."""
|
|
62
|
+
|
|
63
|
+
id: str = Field(min_length=1)
|
|
64
|
+
item_id: str = Field(alias="itemId", min_length=1)
|
|
65
|
+
position: float
|
|
66
|
+
name: str = Field(min_length=1)
|
|
67
|
+
value: str
|
|
68
|
+
owner: str = Field(min_length=1)
|
|
69
|
+
type: str = Field(min_length=1)
|
|
70
|
+
parsed_value: Optional[Union[int, float, List[Any], str]] = Field(alias="parsedValue", default=None)
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def typed_value(self) -> Union[int, float, List[Any], str]:
|
|
74
|
+
"""Get the properly typed value, falling back to raw string if parsing failed."""
|
|
75
|
+
return self.parsed_value if self.parsed_value is not None else self.value
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class DateProperty(BaseModel):
|
|
79
|
+
"""Date property representation."""
|
|
80
|
+
|
|
81
|
+
id: str = Field(min_length=1)
|
|
82
|
+
item_id: str = Field(alias="itemId", min_length=1)
|
|
83
|
+
position: float
|
|
84
|
+
name: str = Field(min_length=1)
|
|
85
|
+
value: str
|
|
86
|
+
owner: str = Field(min_length=1)
|
|
87
|
+
type: str = Field(min_length=1)
|
|
88
|
+
parsed_value: Optional[str] = Field(alias="parsedValue", default=None)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def typed_value(self) -> str:
|
|
92
|
+
"""Get the properly typed value, falling back to raw string if parsing failed."""
|
|
93
|
+
return self.parsed_value if self.parsed_value is not None else self.value
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class PropertySearchResult(BaseModel):
|
|
97
|
+
"""Property search result with unified fields across all property types."""
|
|
98
|
+
|
|
99
|
+
id: str = Field(min_length=1)
|
|
100
|
+
workspace_id: str = Field(alias="workspaceId", min_length=1)
|
|
101
|
+
product_id: str = Field(alias="productId", min_length=1)
|
|
102
|
+
item_id: str = Field(alias="itemId", min_length=1)
|
|
103
|
+
property_type: str = Field(alias="propertyType", min_length=1)
|
|
104
|
+
name: str = Field(min_length=1)
|
|
105
|
+
category: Optional[str] = None
|
|
106
|
+
display_unit: Optional[str] = Field(alias="displayUnit", default=None)
|
|
107
|
+
value: Any # Raw value from GraphQL
|
|
108
|
+
parsed_value: Optional[Union[int, float, List[Any], str]] = Field(alias="parsedValue", default=None)
|
|
109
|
+
owner: str = Field(min_length=1)
|
|
110
|
+
created_by: str = Field(alias="createdBy", min_length=1)
|
|
111
|
+
created_at: str = Field(alias="createdAt", min_length=1)
|
|
112
|
+
updated_at: str = Field(alias="updatedAt", min_length=1)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def typed_value(self) -> Union[int, float, List[Any], str]:
|
|
116
|
+
"""Get the properly typed value, falling back to raw string if parsing failed."""
|
|
117
|
+
return self.parsed_value if self.parsed_value is not None else self.value
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class PropertySearchResponse(BaseModel):
|
|
121
|
+
"""Response for property search queries."""
|
|
122
|
+
|
|
123
|
+
query: str
|
|
124
|
+
hits: List[PropertySearchResult]
|
|
125
|
+
total: int
|
|
126
|
+
limit: int
|
|
127
|
+
offset: int
|
|
128
|
+
processing_time_ms: int = Field(alias="processingTimeMs")
|
|
129
|
+
|
|
130
|
+
|
poelis_sdk/search.py
CHANGED
|
@@ -54,7 +54,7 @@ class SearchClient:
|
|
|
54
54
|
"query($q: String!, $ws: ID, $pid: ID, $iid: ID, $ptype: String, $cat: String, $limit: Int!, $offset: Int!, $sort: String) {\n"
|
|
55
55
|
" searchProperties(q: $q, workspaceId: $ws, productId: $pid, itemId: $iid, propertyType: $ptype, category: $cat, limit: $limit, offset: $offset, sort: $sort) {\n"
|
|
56
56
|
" query total limit offset processingTimeMs\n"
|
|
57
|
-
" hits { id workspaceId productId itemId propertyType name category value owner }\n"
|
|
57
|
+
" hits { id workspaceId productId itemId propertyType name category value parsedValue owner }\n"
|
|
58
58
|
" }\n"
|
|
59
59
|
"}"
|
|
60
60
|
)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
poelis_sdk/__init__.py,sha256=vRKuvnMGtq2_6SYDPNpckSPYXTgMDD1vBAfZ1bXlHL0,924
|
|
2
2
|
poelis_sdk/_transport.py,sha256=Na1neuS9JyLwHqhWkqwpQiGdbRtS0EJlWd587kQ88-s,7069
|
|
3
|
-
poelis_sdk/browser.py,sha256=
|
|
3
|
+
poelis_sdk/browser.py,sha256=drWI86XKhVCcwOO27HD3gSRyLoJG13Ak5RZE0HC95WA,25183
|
|
4
4
|
poelis_sdk/client.py,sha256=10__5po-foX36ZCCduQmzdoh9NNS320kyaqztUNtPvo,3872
|
|
5
5
|
poelis_sdk/exceptions.py,sha256=qX5kpAr8ozJUOW-CNhmspWVIE-bvUZT_PUnimYuBxNY,1101
|
|
6
6
|
poelis_sdk/items.py,sha256=vomXn43gcUlX2iUro3mpb8Qicmmt4sWFB2vXXxIfLsM,2575
|
|
7
7
|
poelis_sdk/logging.py,sha256=zmg8Us-7qjDl0n_NfOSvDolLopy7Dc_hQ-pcrC63dY8,2442
|
|
8
|
-
poelis_sdk/models.py,sha256=
|
|
8
|
+
poelis_sdk/models.py,sha256=PduXuivhpJDjR_MmYYrZ1ha5IFPT8AW0jdm_wOrN2zA,4478
|
|
9
9
|
poelis_sdk/org_validation.py,sha256=c4fB6ySTvcovWxG4F1wU_OBlP-FyuIaAUzCwqgJKzBE,5607
|
|
10
10
|
poelis_sdk/products.py,sha256=bwV2mOPvBriy83F3BxWww1oSsyLZFQvh4XOiIE9fI1s,3240
|
|
11
|
-
poelis_sdk/search.py,sha256=
|
|
11
|
+
poelis_sdk/search.py,sha256=3DqFd7ilTpizjOYgWplR7MTslnY89Q8AmUfn865TnKc,4113
|
|
12
12
|
poelis_sdk/workspaces.py,sha256=hpmRl-Hswr4YDvObQdyVpegIYjUWno7A_BiVBz-AQGc,2383
|
|
13
|
-
poelis_sdk-0.3.
|
|
14
|
-
poelis_sdk-0.3.
|
|
15
|
-
poelis_sdk-0.3.
|
|
16
|
-
poelis_sdk-0.3.
|
|
13
|
+
poelis_sdk-0.3.3.dist-info/METADATA,sha256=ipFrZcuCD5mRUbKJrpBnO7Ix6XozSYM4Nxh4tDIsXE8,2968
|
|
14
|
+
poelis_sdk-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
15
|
+
poelis_sdk-0.3.3.dist-info/licenses/LICENSE,sha256=EEmE_r8wk_pdXB8CWp1LG6sBOl7--hNSS2kV94cI6co,1075
|
|
16
|
+
poelis_sdk-0.3.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|