poelis-sdk 0.1.7__tar.gz → 0.1.9__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.

Potentially problematic release.


This version of poelis-sdk might be problematic. Click here for more details.

Files changed (30) hide show
  1. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/PKG-INFO +1 -1
  2. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/notebooks/try_poelis_sdk.ipynb +1 -9
  3. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/pyproject.toml +1 -1
  4. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/browser.py +31 -9
  5. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/items.py +3 -12
  6. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/models.py +3 -2
  7. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/products.py +3 -8
  8. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/uv.lock +1 -1
  9. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/.github/workflows/ci.yml +0 -0
  10. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/.github/workflows/codeql.yml +0 -0
  11. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/.github/workflows/publish-on-push.yml +0 -0
  12. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/.gitignore +0 -0
  13. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/LICENSE +0 -0
  14. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/README.md +0 -0
  15. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/__init__.py +0 -0
  16. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/_transport.py +0 -0
  17. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/auth0.py +0 -0
  18. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/client.py +0 -0
  19. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/exceptions.py +0 -0
  20. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/logging.py +0 -0
  21. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/org_validation.py +0 -0
  22. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/search.py +0 -0
  23. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/poelis_sdk/workspaces.py +0 -0
  24. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/tests/test_client_basic.py +0 -0
  25. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/tests/test_errors_and_backoff.py +0 -0
  26. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/tests/test_items_client.py +0 -0
  27. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/tests/test_search_client.py +0 -0
  28. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/src/tests/test_transport_and_products.py +0 -0
  29. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/tests/__init__.py +0 -0
  30. {poelis_sdk-0.1.7 → poelis_sdk-0.1.9}/tests/test_integration_smoke.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poelis-sdk
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: Official Python SDK for Poelis
5
5
  Project-URL: Homepage, https://poelis.com
6
6
  Project-URL: Source, https://github.com/PoelisTechnologies/poelis-python-sdk
@@ -47,15 +47,7 @@
47
47
  "cell_type": "code",
48
48
  "execution_count": null,
49
49
  "metadata": {},
50
- "outputs": [
51
- {
52
- "name": "stdout",
53
- "output_type": "stream",
54
- "text": [
55
- "The folder you are executing pip from can no longer be found.\n"
56
- ]
57
- }
58
- ],
50
+ "outputs": [],
59
51
  "source": [
60
52
  "!pip install -U poelis-sdk"
61
53
  ]
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "poelis-sdk"
7
- version = "0.1.7"
7
+ version = "0.1.9"
8
8
  description = "Official Python SDK for Poelis"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -99,11 +99,11 @@ class _Node:
99
99
  if self._level != "item":
100
100
  self._props_cache = []
101
101
  return self._props_cache
102
- # Try direct properties(item_id: ...) first; fallback to searchProperties
102
+ # Try direct properties(itemId: ...) first; fallback to searchProperties
103
103
  q = (
104
104
  "query($iid: ID!) {\n"
105
- " properties(item_id: $iid) {\n"
106
- " __typename id name owner\n"
105
+ " properties(itemId: $iid) {\n"
106
+ " __typename\n"
107
107
  " ... on NumericProperty { integerPart exponent category }\n"
108
108
  " ... on TextProperty { value }\n"
109
109
  " ... on DateProperty { value }\n"
@@ -121,7 +121,7 @@ class _Node:
121
121
  q2 = (
122
122
  "query($iid: ID!, $limit: Int!, $offset: Int!) {\n"
123
123
  " searchProperties(q: \"*\", itemId: $iid, limit: $limit, offset: $offset) {\n"
124
- " hits { id name propertyType category textValue numericValue dateValue owner }\n"
124
+ " hits { id workspaceId productId itemId propertyType name category value owner }\n"
125
125
  " }\n"
126
126
  "}"
127
127
  )
@@ -139,9 +139,19 @@ class _Node:
139
139
  if self._level != "item":
140
140
  return out
141
141
  props = self.properties
142
- for pr in props:
143
- display = pr.get("name") or pr.get("id")
142
+ used_names: Dict[str, int] = {}
143
+ for i, pr in enumerate(props):
144
+ # Try to get name from various possible fields
145
+ display = pr.get("name") or pr.get("id") or pr.get("category") or f"property_{i}"
144
146
  safe = _safe_key(str(display))
147
+
148
+ # Handle duplicate names by adding a suffix
149
+ if safe in used_names:
150
+ used_names[safe] += 1
151
+ safe = f"{safe}_{used_names[safe]}"
152
+ else:
153
+ used_names[safe] = 0
154
+
145
155
  out[safe] = _PropWrapper(pr)
146
156
  return out
147
157
 
@@ -246,11 +256,23 @@ class _PropsNode:
246
256
  if self._children_cache:
247
257
  return
248
258
  props = self._item.properties
249
- for pr in props:
250
- display = pr.get("name") or pr.get("id")
259
+ used_names: Dict[str, int] = {}
260
+ names_list = []
261
+ for i, pr in enumerate(props):
262
+ # Try to get name from various possible fields
263
+ display = pr.get("name") or pr.get("id") or pr.get("category") or f"property_{i}"
251
264
  safe = _safe_key(str(display))
265
+
266
+ # Handle duplicate names by adding a suffix
267
+ if safe in used_names:
268
+ used_names[safe] += 1
269
+ safe = f"{safe}_{used_names[safe]}"
270
+ else:
271
+ used_names[safe] = 0
272
+
252
273
  self._children_cache[safe] = _PropWrapper(pr)
253
- self._names = [p.get("name") or p.get("id") for p in props]
274
+ names_list.append(display)
275
+ self._names = names_list
254
276
 
255
277
  def __dir__(self) -> List[str]: # pragma: no cover - notebook UX
256
278
  self._ensure_loaded()
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import Generator, Any, Optional, Dict, List
4
4
 
5
5
  from ._transport import Transport
6
- from .org_validation import validate_item_organization, filter_by_organization
7
6
 
8
7
  """Items resource client."""
9
8
 
@@ -22,7 +21,7 @@ class ItemsClient:
22
21
 
23
22
  query = (
24
23
  "query($pid: ID!, $q: String, $limit: Int!, $offset: Int!) {\n"
25
- " items(productId: $pid, q: $q, limit: $limit, offset: $offset) { id name code description productId parentId owner orgId }\n"
24
+ " items(productId: $pid, q: $q, limit: $limit, offset: $offset) { id name code description productId parentId owner }\n"
26
25
  "}"
27
26
  )
28
27
  variables = {"pid": product_id, "q": q, "limit": int(limit), "offset": int(offset)}
@@ -34,11 +33,7 @@ class ItemsClient:
34
33
 
35
34
  items = payload.get("data", {}).get("items", [])
36
35
 
37
- # Client-side organization filtering as backup protection
38
- expected_org_id = self._t._org_id
39
- filtered_items = filter_by_organization(items, expected_org_id, "items")
40
-
41
- return filtered_items
36
+ return items
42
37
 
43
38
  def get(self, item_id: str) -> Dict[str, Any]:
44
39
  """Get a single item by id via GraphQL.
@@ -48,7 +43,7 @@ class ItemsClient:
48
43
 
49
44
  query = (
50
45
  "query($id: ID!) {\n"
51
- " item(id: $id) { id name code description productId parentId owner orgId }\n"
46
+ " item(id: $id) { id name code description productId parentId owner }\n"
52
47
  "}"
53
48
  )
54
49
  resp = self._t.graphql(query=query, variables={"id": item_id})
@@ -61,10 +56,6 @@ class ItemsClient:
61
56
  if item is None:
62
57
  raise RuntimeError(f"Item with id '{item_id}' not found")
63
58
 
64
- # Validate that the item belongs to the configured organization
65
- expected_org_id = self._t._org_id
66
- validate_item_organization(item, expected_org_id)
67
-
68
59
  return item
69
60
 
70
61
  def iter_all_by_product(self, *, product_id: str, q: Optional[str] = None, page_size: int = 100) -> Generator[dict, None, None]:
@@ -12,8 +12,9 @@ class Product(BaseModel):
12
12
 
13
13
  id: str = Field(min_length=1)
14
14
  name: str = Field(min_length=1)
15
- workspace_id: Optional[str] = None
16
- org_id: Optional[str] = None
15
+ workspaceId: Optional[str] = None
16
+ code: Optional[str] = None
17
+ description: Optional[str] = None
17
18
 
18
19
 
19
20
  class PaginatedProducts(BaseModel):
@@ -1,10 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Generator, Optional, List, TYPE_CHECKING
3
+ from typing import Generator, Optional, TYPE_CHECKING
4
4
 
5
5
  from ._transport import Transport
6
6
  from .models import PaginatedProducts, Product
7
- from .org_validation import filter_by_organization
8
7
 
9
8
  if TYPE_CHECKING:
10
9
  from .workspaces import WorkspacesClient
@@ -33,7 +32,7 @@ class ProductsClient:
33
32
 
34
33
  query = (
35
34
  "query($ws: ID!, $q: String, $limit: Int!, $offset: Int!) {\n"
36
- " products(workspaceId: $ws, q: $q, limit: $limit, offset: $offset) { id name code description workspaceId orgId }\n"
35
+ " products(workspaceId: $ws, q: $q, limit: $limit, offset: $offset) { id name workspaceId code description }\n"
37
36
  "}"
38
37
  )
39
38
  variables = {"ws": workspace_id, "q": q, "limit": int(limit), "offset": int(offset)}
@@ -45,11 +44,7 @@ class ProductsClient:
45
44
 
46
45
  products = payload.get("data", {}).get("products", [])
47
46
 
48
- # Client-side organization filtering as backup protection
49
- expected_org_id = self._t._org_id
50
- filtered_products = filter_by_organization(products, expected_org_id, "products")
51
-
52
- return PaginatedProducts(data=[Product(**r) for r in filtered_products], limit=limit, offset=offset)
47
+ return PaginatedProducts(data=[Product(**r) for r in products], limit=limit, offset=offset)
53
48
 
54
49
  def iter_all_by_workspace(self, *, workspace_id: str, q: Optional[str] = None, page_size: int = 100, start_offset: int = 0) -> Generator[Product, None, None]:
55
50
  """Iterate products via GraphQL with offset pagination for a workspace."""
@@ -538,7 +538,7 @@ wheels = [
538
538
 
539
539
  [[package]]
540
540
  name = "poelis-sdk"
541
- version = "0.1.7"
541
+ version = "0.1.9"
542
542
  source = { editable = "." }
543
543
  dependencies = [
544
544
  { name = "build" },
File without changes
File without changes
File without changes
File without changes