poelis-sdk 0.4.2__tar.gz → 0.5.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.
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/.gitignore +2 -0
- poelis_sdk-0.5.3/.poelis/baseline.json +14 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/PKG-INFO +30 -45
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/README.md +29 -44
- poelis_sdk-0.5.3/notebooks/try_poelis_sdk.ipynb +286 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/pyproject.toml +1 -1
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/_transport.py +3 -24
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/browser.py +457 -120
- poelis_sdk-0.5.3/src/poelis_sdk/change_tracker.py +757 -0
- poelis_sdk-0.5.3/src/poelis_sdk/client.py +204 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/org_validation.py +10 -4
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/workspaces.py +3 -22
- poelis_sdk-0.5.3/src/tests/test_change_detection.py +405 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/tests/test_client_basic.py +11 -13
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/tests/test_errors_and_backoff.py +2 -3
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/tests/test_items_client.py +2 -3
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/tests/test_search_client.py +2 -3
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/tests/test_transport_and_products.py +5 -7
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/tests/test_browser_navigation.py +17 -20
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/tests/test_integration_smoke.py +3 -4
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/uv.lock +1 -1
- poelis_sdk-0.4.2/notebooks/try_poelis_sdk.ipynb +0 -614
- poelis_sdk-0.4.2/src/poelis_sdk/client.py +0 -123
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/.github/workflows/ci.yml +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/.github/workflows/codeql.yml +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/.github/workflows/publish-on-push.yml +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/LICENSE +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/__init__.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/exceptions.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/items.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/logging.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/models.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/products.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/search.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/src/poelis_sdk/versions.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/tests/__init__.py +0 -0
- {poelis_sdk-0.4.2 → poelis_sdk-0.5.3}/tests/test_typed_properties.py +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"baselines": {
|
|
3
|
+
"prop1": {
|
|
4
|
+
"value": 150.0,
|
|
5
|
+
"name": "Price",
|
|
6
|
+
"first_accessed_at": 1764778693.876765,
|
|
7
|
+
"updated_at": null,
|
|
8
|
+
"updated_by": null
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"accessed_items": {},
|
|
12
|
+
"accessed_properties": {},
|
|
13
|
+
"last_updated": 1764778693.8768158
|
|
14
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: poelis-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.3
|
|
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
|
|
@@ -25,42 +25,46 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
|
|
26
26
|
Python SDK for Poelis - explore your data with simple dot notation.
|
|
27
27
|
|
|
28
|
+
## IDE Compatibility & Autocomplete
|
|
29
|
+
|
|
30
|
+
The Poelis SDK works in all Python environments, but autocomplete behavior varies by IDE:
|
|
31
|
+
|
|
32
|
+
### ✅ VS Code (Recommended for Notebooks)
|
|
33
|
+
- **Autocomplete**: Works perfectly with dynamic attributes
|
|
34
|
+
- **Setup**: No configuration needed
|
|
35
|
+
- **Experience**: Full autocomplete at all levels
|
|
36
|
+
|
|
37
|
+
### ⚠️ PyCharm (Jupyter Notebooks)
|
|
38
|
+
- **Autocomplete**: Limited - PyCharm uses static analysis and doesn't see dynamic attributes
|
|
39
|
+
- **Code execution**: Works perfectly (attributes are real and functional)
|
|
40
|
+
- **Workaround**: Call the relevant `list_*().names` at each level to prime autocomplete
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
See `notebooks/try_poelis_sdk.ipynb` for complete examples including authentication, data exploration, and search queries.
|
|
45
|
+
|
|
28
46
|
## Installation
|
|
29
47
|
|
|
48
|
+
- Python >= 3.11
|
|
49
|
+
- API base URL reachable from your environment
|
|
50
|
+
|
|
30
51
|
```bash
|
|
31
52
|
pip install -U poelis-sdk
|
|
32
53
|
```
|
|
33
54
|
|
|
34
|
-
Requires Python 3.11+.
|
|
35
|
-
|
|
36
55
|
## Quick Start
|
|
37
56
|
|
|
57
|
+
1. Go to **Organization Settings → API Keys**
|
|
58
|
+
2. Click **\"Create API key\"**
|
|
59
|
+
3. Copy the key (shown only once) and store it securely, for example as an environment variable:
|
|
60
|
+
|
|
38
61
|
```python
|
|
39
62
|
from poelis_sdk import PoelisClient
|
|
40
63
|
|
|
41
64
|
# Create client
|
|
42
|
-
|
|
65
|
+
poelis_client = PoelisClient(
|
|
43
66
|
api_key="poelis_live_A1B2C3...", # Get from Organization Settings → API Keys
|
|
44
|
-
org_id="tenant_uci_001", # Same section
|
|
45
67
|
)
|
|
46
|
-
|
|
47
|
-
# Use the browser for easy exploration
|
|
48
|
-
poelis = poelis.browser # Now you can use dot notation!
|
|
49
|
-
|
|
50
|
-
# Explore your data
|
|
51
|
-
poelis.workspace_name.product_name.item_name
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Getting Your Credentials
|
|
55
|
-
|
|
56
|
-
1. Go to **Organization Settings → API Keys**
|
|
57
|
-
2. Click **"Create API key"** (read-only recommended)
|
|
58
|
-
3. Copy the key (shown only once) and your `org_id`
|
|
59
|
-
4. Store securely as environment variables:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
export POELIS_API_KEY=poelis_live_A1B2C3...
|
|
63
|
-
export POELIS_ORG_ID=tenant_uci_001
|
|
64
68
|
```
|
|
65
69
|
|
|
66
70
|
## Browser Usage
|
|
@@ -69,7 +73,7 @@ The browser lets you navigate your Poelis data with simple dot notation:
|
|
|
69
73
|
|
|
70
74
|
```python
|
|
71
75
|
# Navigate through your data
|
|
72
|
-
poelis =
|
|
76
|
+
poelis = poelis_client.browser
|
|
73
77
|
|
|
74
78
|
# List workspaces
|
|
75
79
|
poelis.list_workspaces().names # ['workspace1', 'workspace2', ...]
|
|
@@ -97,31 +101,12 @@ item.list_properties().names # ['Color', 'Weight', ...] - only properties
|
|
|
97
101
|
item_value = item.some_property.value # Access property values directly
|
|
98
102
|
item_category = item.some_property.category # Access property categories directly
|
|
99
103
|
item_unit = item.some_property.unit # Access property units directly
|
|
100
|
-
|
|
101
104
|
```
|
|
102
105
|
|
|
103
|
-
##
|
|
104
|
-
|
|
105
|
-
The Poelis SDK works in all Python environments, but autocomplete behavior varies by IDE:
|
|
106
|
-
|
|
107
|
-
### ✅ VS Code (Recommended for Notebooks)
|
|
108
|
-
- **Autocomplete**: Works perfectly with dynamic attributes
|
|
109
|
-
- **Setup**: No configuration needed
|
|
110
|
-
- **Experience**: Full autocomplete at all levels
|
|
111
|
-
|
|
112
|
-
### ⚠️ PyCharm (Jupyter Notebooks)
|
|
113
|
-
- **Autocomplete**: Limited - PyCharm uses static analysis and doesn't see dynamic attributes
|
|
114
|
-
- **Code execution**: Works perfectly (attributes are real and functional)
|
|
115
|
-
- **Workaround**: Call the relevant `list_*().names` at each level to prime autocomplete
|
|
106
|
+
## Property Change Detection
|
|
116
107
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
See `notebooks/try_poelis_sdk.ipynb` for complete examples including authentication, data exploration, and search queries.
|
|
108
|
+
The SDK can automatically warn you when property values change between script/notebook runs. This is useful when you're using property values for calculations and want to be notified if a colleague changes them in the webapp.
|
|
120
109
|
|
|
121
|
-
## Requirements
|
|
122
|
-
|
|
123
|
-
- Python >= 3.11
|
|
124
|
-
- API base URL reachable from your environment
|
|
125
110
|
|
|
126
111
|
## License
|
|
127
112
|
|
|
@@ -2,42 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
Python SDK for Poelis - explore your data with simple dot notation.
|
|
4
4
|
|
|
5
|
+
## IDE Compatibility & Autocomplete
|
|
6
|
+
|
|
7
|
+
The Poelis SDK works in all Python environments, but autocomplete behavior varies by IDE:
|
|
8
|
+
|
|
9
|
+
### ✅ VS Code (Recommended for Notebooks)
|
|
10
|
+
- **Autocomplete**: Works perfectly with dynamic attributes
|
|
11
|
+
- **Setup**: No configuration needed
|
|
12
|
+
- **Experience**: Full autocomplete at all levels
|
|
13
|
+
|
|
14
|
+
### ⚠️ PyCharm (Jupyter Notebooks)
|
|
15
|
+
- **Autocomplete**: Limited - PyCharm uses static analysis and doesn't see dynamic attributes
|
|
16
|
+
- **Code execution**: Works perfectly (attributes are real and functional)
|
|
17
|
+
- **Workaround**: Call the relevant `list_*().names` at each level to prime autocomplete
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
See `notebooks/try_poelis_sdk.ipynb` for complete examples including authentication, data exploration, and search queries.
|
|
22
|
+
|
|
5
23
|
## Installation
|
|
6
24
|
|
|
25
|
+
- Python >= 3.11
|
|
26
|
+
- API base URL reachable from your environment
|
|
27
|
+
|
|
7
28
|
```bash
|
|
8
29
|
pip install -U poelis-sdk
|
|
9
30
|
```
|
|
10
31
|
|
|
11
|
-
Requires Python 3.11+.
|
|
12
|
-
|
|
13
32
|
## Quick Start
|
|
14
33
|
|
|
34
|
+
1. Go to **Organization Settings → API Keys**
|
|
35
|
+
2. Click **\"Create API key\"**
|
|
36
|
+
3. Copy the key (shown only once) and store it securely, for example as an environment variable:
|
|
37
|
+
|
|
15
38
|
```python
|
|
16
39
|
from poelis_sdk import PoelisClient
|
|
17
40
|
|
|
18
41
|
# Create client
|
|
19
|
-
|
|
42
|
+
poelis_client = PoelisClient(
|
|
20
43
|
api_key="poelis_live_A1B2C3...", # Get from Organization Settings → API Keys
|
|
21
|
-
org_id="tenant_uci_001", # Same section
|
|
22
44
|
)
|
|
23
|
-
|
|
24
|
-
# Use the browser for easy exploration
|
|
25
|
-
poelis = poelis.browser # Now you can use dot notation!
|
|
26
|
-
|
|
27
|
-
# Explore your data
|
|
28
|
-
poelis.workspace_name.product_name.item_name
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Getting Your Credentials
|
|
32
|
-
|
|
33
|
-
1. Go to **Organization Settings → API Keys**
|
|
34
|
-
2. Click **"Create API key"** (read-only recommended)
|
|
35
|
-
3. Copy the key (shown only once) and your `org_id`
|
|
36
|
-
4. Store securely as environment variables:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
export POELIS_API_KEY=poelis_live_A1B2C3...
|
|
40
|
-
export POELIS_ORG_ID=tenant_uci_001
|
|
41
45
|
```
|
|
42
46
|
|
|
43
47
|
## Browser Usage
|
|
@@ -46,7 +50,7 @@ The browser lets you navigate your Poelis data with simple dot notation:
|
|
|
46
50
|
|
|
47
51
|
```python
|
|
48
52
|
# Navigate through your data
|
|
49
|
-
poelis =
|
|
53
|
+
poelis = poelis_client.browser
|
|
50
54
|
|
|
51
55
|
# List workspaces
|
|
52
56
|
poelis.list_workspaces().names # ['workspace1', 'workspace2', ...]
|
|
@@ -74,31 +78,12 @@ item.list_properties().names # ['Color', 'Weight', ...] - only properties
|
|
|
74
78
|
item_value = item.some_property.value # Access property values directly
|
|
75
79
|
item_category = item.some_property.category # Access property categories directly
|
|
76
80
|
item_unit = item.some_property.unit # Access property units directly
|
|
77
|
-
|
|
78
81
|
```
|
|
79
82
|
|
|
80
|
-
##
|
|
81
|
-
|
|
82
|
-
The Poelis SDK works in all Python environments, but autocomplete behavior varies by IDE:
|
|
83
|
-
|
|
84
|
-
### ✅ VS Code (Recommended for Notebooks)
|
|
85
|
-
- **Autocomplete**: Works perfectly with dynamic attributes
|
|
86
|
-
- **Setup**: No configuration needed
|
|
87
|
-
- **Experience**: Full autocomplete at all levels
|
|
88
|
-
|
|
89
|
-
### ⚠️ PyCharm (Jupyter Notebooks)
|
|
90
|
-
- **Autocomplete**: Limited - PyCharm uses static analysis and doesn't see dynamic attributes
|
|
91
|
-
- **Code execution**: Works perfectly (attributes are real and functional)
|
|
92
|
-
- **Workaround**: Call the relevant `list_*().names` at each level to prime autocomplete
|
|
83
|
+
## Property Change Detection
|
|
93
84
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
See `notebooks/try_poelis_sdk.ipynb` for complete examples including authentication, data exploration, and search queries.
|
|
85
|
+
The SDK can automatically warn you when property values change between script/notebook runs. This is useful when you're using property values for calculations and want to be notified if a colleague changes them in the webapp.
|
|
97
86
|
|
|
98
|
-
## Requirements
|
|
99
|
-
|
|
100
|
-
- Python >= 3.11
|
|
101
|
-
- API base URL reachable from your environment
|
|
102
87
|
|
|
103
88
|
## License
|
|
104
89
|
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Poelis Python SDK Tutorial\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Welcome to the Poelis Python SDK tutorial! This notebook will guide you through setting up and using the SDK to interact with the Poelis API.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"### What is Poelis?\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"Poelis is a platform for managing hierarchical data structures, products, items, and their properties. The Python SDK provides a convenient way to interact with the Poelis API from your Python applications.\n",
|
|
14
|
+
"\n",
|
|
15
|
+
"### Table of Contents\n",
|
|
16
|
+
"\n",
|
|
17
|
+
"1. [Installation](#1-installation)\n",
|
|
18
|
+
"2. [IDE Compatibility & Autocomplete](#2-ide-compatibility--autocomplete)\n",
|
|
19
|
+
"3. [Authentication & Client Setup](#3-authentication--client-setup)\n",
|
|
20
|
+
"4. [Browser Interface](#4-browser-interface)\n",
|
|
21
|
+
"5. [Product Versions](#5-product-versions)\n",
|
|
22
|
+
"\n"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"cell_type": "markdown",
|
|
27
|
+
"metadata": {},
|
|
28
|
+
"source": [
|
|
29
|
+
"## 1. Installation\n",
|
|
30
|
+
"\n",
|
|
31
|
+
"### Requirements\n",
|
|
32
|
+
"- Python >= 3.11\n",
|
|
33
|
+
"- Access to a Poelis API endpoint\n",
|
|
34
|
+
"- Valid SDK API key (user-bound; org/workspaces derived server-side)\n"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"cell_type": "code",
|
|
39
|
+
"execution_count": null,
|
|
40
|
+
"metadata": {},
|
|
41
|
+
"outputs": [],
|
|
42
|
+
"source": [
|
|
43
|
+
"!pip install -U poelis-sdk"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"cell_type": "markdown",
|
|
48
|
+
"metadata": {},
|
|
49
|
+
"source": [
|
|
50
|
+
"## 2. IDE Compatibility & Autocomplete\n",
|
|
51
|
+
"\n",
|
|
52
|
+
"The Poelis SDK works great in both **VS Code** and **PyCharm**, but there are some differences in how autocomplete behaves:\n",
|
|
53
|
+
"\n",
|
|
54
|
+
"### VS Code (Recommended for Best Experience)\n",
|
|
55
|
+
"- ✅ **Perfect autocomplete**: Dynamic attributes work automatically\n",
|
|
56
|
+
"- ✅ **No setup required**: Just start typing and press TAB\n",
|
|
57
|
+
"- ✅ **Fast and responsive**: Real-time completion suggestions\n",
|
|
58
|
+
"- ✅ **Works in Jupyter notebooks**: Full autocomplete support\n",
|
|
59
|
+
"\n",
|
|
60
|
+
"### PyCharm (Good, but with limitations)\n",
|
|
61
|
+
"- ⚠️ **Limited autocomplete**: Uses static analysis, not runtime introspection\n",
|
|
62
|
+
"- ⚠️ **Requires priming**: Call `names()` at each level for autocomplete\n",
|
|
63
|
+
"- ✅ **Code works perfectly**: All functionality works, just autocomplete is limited\n",
|
|
64
|
+
"- ✅ **Workarounds available**: Interactive selectors and helper functions\n",
|
|
65
|
+
"\n",
|
|
66
|
+
"**Recommendation**: Use **VS Code** for the best autocomplete experience, especially in Jupyter notebooks.\n",
|
|
67
|
+
"\n",
|
|
68
|
+
"### Notebooks vs Python Scripts\n",
|
|
69
|
+
"\n",
|
|
70
|
+
"**In Jupyter Notebooks**: The browser interface works great! You get autocomplete (especially in VS Code) and can easily explore your data interactively using dot notation like `poelis.demo_workspace.demo_product`.\n",
|
|
71
|
+
"\n",
|
|
72
|
+
"**In Python Scripts**: For better reliability and performance, it's recommended to copy IDs from the webapp and use them directly.\n"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"cell_type": "markdown",
|
|
77
|
+
"metadata": {},
|
|
78
|
+
"source": [
|
|
79
|
+
"## 3. Authentication & Client Setup\n",
|
|
80
|
+
"\n",
|
|
81
|
+
"Before you can use the SDK, you need to set up authentication and initialize the client.\n",
|
|
82
|
+
"\n",
|
|
83
|
+
"### Getting Your Credentials\n",
|
|
84
|
+
"\n",
|
|
85
|
+
"1. **Navigate to Organization Settings → API Keys** in the Poelis web interface\n",
|
|
86
|
+
"2. **Create a new SDK API key**\n",
|
|
87
|
+
"3. **Important**: SDK keys are **user-bound**; organization and workspace access are derived on the server from the Poelis user behind that key.\n",
|
|
88
|
+
"4. With this key, you only see the workspaces your Poelis user is assigned to in that org."
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"cell_type": "code",
|
|
93
|
+
"execution_count": null,
|
|
94
|
+
"metadata": {},
|
|
95
|
+
"outputs": [],
|
|
96
|
+
"source": [
|
|
97
|
+
"# Import the SDK\n",
|
|
98
|
+
"from poelis_sdk import PoelisClient\n",
|
|
99
|
+
"\n",
|
|
100
|
+
"# Example: Initialize client (replace with your actual API key)\n",
|
|
101
|
+
"\n",
|
|
102
|
+
"poelis_client = PoelisClient(\n",
|
|
103
|
+
" api_key=\"your_api_key_here\",\n",
|
|
104
|
+
")\n",
|
|
105
|
+
"\n",
|
|
106
|
+
"poelis = poelis_client.browser"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"cell_type": "markdown",
|
|
111
|
+
"metadata": {},
|
|
112
|
+
"source": [
|
|
113
|
+
"## 4. Browser Interface\n",
|
|
114
|
+
"\n",
|
|
115
|
+
"Navigate your data using dot notation: `poelis.<workspace>.<product>.<item>.<property>`\n",
|
|
116
|
+
"\n",
|
|
117
|
+
"**IDE Note**: VS Code has perfect autocomplete. PyCharm users should use `list_*().names` to discover available names.\n",
|
|
118
|
+
"\n",
|
|
119
|
+
"### Available Functions\n",
|
|
120
|
+
"\n",
|
|
121
|
+
"#### 1. `list_workspaces()` - List all workspaces\n",
|
|
122
|
+
"\n",
|
|
123
|
+
"#### 2. `list_products()` - List products in a workspace\n",
|
|
124
|
+
"\n",
|
|
125
|
+
"#### 3. `list_items()` - List items in a product/item\n",
|
|
126
|
+
"\n",
|
|
127
|
+
"#### 4. `list_properties()` - List properties of an item\n",
|
|
128
|
+
"\n",
|
|
129
|
+
"#### 5. `get_property(readable_id)` - Get property by readableId\n",
|
|
130
|
+
"\n",
|
|
131
|
+
"\n",
|
|
132
|
+
"## Property Change Detection\n",
|
|
133
|
+
"\n",
|
|
134
|
+
"The SDK can automatically warn you when property values change between script/notebook runs. This is useful when you're using property values for calculations and want to be notified if a colleague changes them in the webapp.\n"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"cell_type": "code",
|
|
139
|
+
"execution_count": null,
|
|
140
|
+
"metadata": {},
|
|
141
|
+
"outputs": [],
|
|
142
|
+
"source": [
|
|
143
|
+
"# Example: list_workspaces()\n",
|
|
144
|
+
"workspaces = poelis.list_workspaces().names\n",
|
|
145
|
+
"print(\"Available workspaces:\", workspaces)"
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"cell_type": "code",
|
|
150
|
+
"execution_count": null,
|
|
151
|
+
"metadata": {},
|
|
152
|
+
"outputs": [],
|
|
153
|
+
"source": [
|
|
154
|
+
"# Example: list_products()\n",
|
|
155
|
+
"ws = poelis.demo_workspace # Replace with your workspace name\n",
|
|
156
|
+
"products = ws.list_products().names\n",
|
|
157
|
+
"print(\"Products in workspace:\", products)"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"cell_type": "code",
|
|
162
|
+
"execution_count": null,
|
|
163
|
+
"metadata": {},
|
|
164
|
+
"outputs": [],
|
|
165
|
+
"source": [
|
|
166
|
+
"# Example: list_items()\n",
|
|
167
|
+
"prod = ws.demo_product\n",
|
|
168
|
+
"items = prod.list_items().names\n",
|
|
169
|
+
"print(items) # ['item1', 'item2', ...]\n",
|
|
170
|
+
"\n",
|
|
171
|
+
"# At item level: lists only child items (not properties)\n",
|
|
172
|
+
"item = prod.demo_item\n",
|
|
173
|
+
"child_items = item.list_items().names"
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"cell_type": "code",
|
|
178
|
+
"execution_count": null,
|
|
179
|
+
"metadata": {},
|
|
180
|
+
"outputs": [],
|
|
181
|
+
"source": [
|
|
182
|
+
"# Example: list_properties()\n",
|
|
183
|
+
"item = prod.demo_item # Replace with your item name\n",
|
|
184
|
+
"properties = item.list_properties().names\n",
|
|
185
|
+
"print(\"Properties:\", properties)"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"cell_type": "code",
|
|
190
|
+
"execution_count": null,
|
|
191
|
+
"metadata": {},
|
|
192
|
+
"outputs": [],
|
|
193
|
+
"source": [
|
|
194
|
+
"# Example: get_property(readable_id)\n",
|
|
195
|
+
"property_readable_id = \"demo_property_mass\" # Replace with your property's readableId\n",
|
|
196
|
+
"prop = prod.get_property(property_readable_id)\n",
|
|
197
|
+
"print(f\"Value: {prop.value}, Category: {prop.category}, Unit: {prop.unit}\")"
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"cell_type": "markdown",
|
|
202
|
+
"metadata": {},
|
|
203
|
+
"source": [
|
|
204
|
+
"## 5. Product Versions\n",
|
|
205
|
+
"\n",
|
|
206
|
+
"Poelis supports **product versioning**, which allows you to create frozen snapshots of your product data at specific points in time. This is useful for tracking changes, maintaining historical records, and ensuring reproducibility.\n",
|
|
207
|
+
"\n",
|
|
208
|
+
"### Understanding Versions\n",
|
|
209
|
+
"\n",
|
|
210
|
+
"- **Draft**: The current working state of your product (not yet versioned)\n",
|
|
211
|
+
"- **Versioned snapshots**: Frozen snapshots of your product at specific version numbers (v1, v2, v3, etc.)\n",
|
|
212
|
+
"- **Baseline**: The latest versioned snapshot (highest version number)\n",
|
|
213
|
+
"\n",
|
|
214
|
+
"**Important**: When you access a product without specifying a version (e.g., `product.my_item`), the SDK defaults to the **baseline** version (the latest versioned snapshot). If no versions exist yet, it falls back to the draft.\n",
|
|
215
|
+
"\n",
|
|
216
|
+
"### Available Functions\n",
|
|
217
|
+
"\n",
|
|
218
|
+
"#### 1. `list_product_versions()` - List all versions of a product\n",
|
|
219
|
+
"\n",
|
|
220
|
+
"#### 2. `get_version()` - Access a version of a product by its title"
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"cell_type": "code",
|
|
225
|
+
"execution_count": null,
|
|
226
|
+
"metadata": {},
|
|
227
|
+
"outputs": [],
|
|
228
|
+
"source": [
|
|
229
|
+
"# Example: List product versions\n",
|
|
230
|
+
"product = poelis.demo_workspace.demo_product # Replace with your product\n",
|
|
231
|
+
"\n",
|
|
232
|
+
"# List all available versions (including draft)\n",
|
|
233
|
+
"versions = product.list_product_versions().names\n",
|
|
234
|
+
"print(\"Available versions:\", versions)"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"cell_type": "code",
|
|
239
|
+
"execution_count": null,
|
|
240
|
+
"metadata": {},
|
|
241
|
+
"outputs": [],
|
|
242
|
+
"source": [
|
|
243
|
+
"# Example: Access different versions via browser interface\n",
|
|
244
|
+
"product = poelis.demo_workspace.demo_product # Replace with your product\n",
|
|
245
|
+
"\n",
|
|
246
|
+
"# Access draft version\n",
|
|
247
|
+
"draft = product.draft\n",
|
|
248
|
+
"print(\"Draft version items:\", draft.list_items().names[:5]) # First 5 items\n",
|
|
249
|
+
"\n",
|
|
250
|
+
"# Access baseline (latest versioned snapshot)\n",
|
|
251
|
+
"baseline = product.baseline\n",
|
|
252
|
+
"print(\"Baseline version items:\", baseline.list_items().names[:5])\n",
|
|
253
|
+
"\n",
|
|
254
|
+
"# Access a specific version (e.g., v1)\n",
|
|
255
|
+
"if \"v1\" in product.list_product_versions().names:\n",
|
|
256
|
+
" v1 = product.v1\n",
|
|
257
|
+
" print(\"Version 1 items:\", v1.list_items().names[:5])\n",
|
|
258
|
+
"\n",
|
|
259
|
+
"# Access a version by name\n",
|
|
260
|
+
"version_prod_2025 = product.get_version(\"PROD 2025\")\n",
|
|
261
|
+
"print(\"Version items:\", version_prod_2025.list_items().names[:5])"
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
],
|
|
265
|
+
"metadata": {
|
|
266
|
+
"kernelspec": {
|
|
267
|
+
"display_name": "Python 3",
|
|
268
|
+
"language": "python",
|
|
269
|
+
"name": "python3"
|
|
270
|
+
},
|
|
271
|
+
"language_info": {
|
|
272
|
+
"codemirror_mode": {
|
|
273
|
+
"name": "ipython",
|
|
274
|
+
"version": 3
|
|
275
|
+
},
|
|
276
|
+
"file_extension": ".py",
|
|
277
|
+
"mimetype": "text/x-python",
|
|
278
|
+
"name": "python",
|
|
279
|
+
"nbconvert_exporter": "python",
|
|
280
|
+
"pygments_lexer": "ipython3",
|
|
281
|
+
"version": "3.11.13"
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"nbformat": 4,
|
|
285
|
+
"nbformat_minor": 2
|
|
286
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import random
|
|
5
4
|
import time
|
|
6
5
|
from typing import Any, Dict, Mapping, Optional
|
|
@@ -32,26 +31,18 @@ class Transport:
|
|
|
32
31
|
in the SDK planning document.
|
|
33
32
|
"""
|
|
34
33
|
|
|
35
|
-
def __init__(self, base_url: str, api_key: str,
|
|
34
|
+
def __init__(self, base_url: str, api_key: str, timeout_seconds: float) -> None:
|
|
36
35
|
"""Initialize the transport.
|
|
37
36
|
|
|
38
37
|
Args:
|
|
39
38
|
base_url: Base API URL.
|
|
40
39
|
api_key: API key provided by backend to authenticate requests.
|
|
41
|
-
org_id: Organization id for tenant scoping.
|
|
42
40
|
timeout_seconds: Request timeout in seconds.
|
|
43
41
|
"""
|
|
44
42
|
|
|
45
43
|
self._client = httpx.Client(base_url=base_url, timeout=timeout_seconds)
|
|
46
44
|
self._api_key = api_key
|
|
47
|
-
self._org_id = org_id
|
|
48
45
|
self._timeout = timeout_seconds
|
|
49
|
-
# Auth mode is intentionally read from environment to keep the public
|
|
50
|
-
# constructor signature stable for tests and backwards-compatibility.
|
|
51
|
-
# Supported values:
|
|
52
|
-
# - "bearer" (default): Authorization: Bearer <api_key>
|
|
53
|
-
# - "api_key": X-API-Key/X-Poelis-Api-Key headers with no Authorization
|
|
54
|
-
self._auth_mode = os.environ.get("POELIS_AUTH_MODE", "api_key").strip().lower()
|
|
55
46
|
|
|
56
47
|
|
|
57
48
|
def _headers(self, extra: Optional[Mapping[str, str]] = None) -> Dict[str, str]:
|
|
@@ -59,20 +50,8 @@ class Transport:
|
|
|
59
50
|
"Accept": "application/json",
|
|
60
51
|
"Content-Type": "application/json",
|
|
61
52
|
}
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
if auth_mode == "api_key":
|
|
65
|
-
# Some staging environments expect an API key header and reject Bearer
|
|
66
|
-
# Include common header variants for compatibility; backend may accept either.
|
|
67
|
-
headers["X-API-Key"] = self._api_key
|
|
68
|
-
headers["X-Poelis-Api-Key"] = self._api_key
|
|
69
|
-
# Additionally include Authorization with Api-Key scheme for services
|
|
70
|
-
# that only read credentials from Authorization.
|
|
71
|
-
headers["Authorization"] = f"Api-Key {self._api_key}"
|
|
72
|
-
else:
|
|
73
|
-
# Default: send API key as Bearer token
|
|
74
|
-
headers["Authorization"] = f"Bearer {self._api_key}"
|
|
75
|
-
headers["X-Poelis-Org"] = self._org_id
|
|
53
|
+
# Always send API key as Bearer token; backend derives org/workspace from key.
|
|
54
|
+
headers["Authorization"] = f"Bearer {self._api_key}"
|
|
76
55
|
if extra:
|
|
77
56
|
headers.update(dict(extra))
|
|
78
57
|
return headers
|