cvec 1.4.3__tar.gz → 1.5.2__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.
- cvec-1.5.2/.claude/settings.json +51 -0
- cvec-1.5.2/.claude/settings.local.json +28 -0
- cvec-1.5.2/.github/workflows/ci.yml +33 -0
- cvec-1.5.2/.github/workflows/license-check-python.yml +17 -0
- cvec-1.5.2/.github/workflows/pyproject-license-check.yml +17 -0
- cvec-1.5.2/.gitignore +177 -0
- cvec-1.5.2/CLAUDE.md +1 -0
- {cvec-1.4.3 → cvec-1.5.2}/PKG-INFO +132 -11
- {cvec-1.4.3 → cvec-1.5.2}/README.md +126 -4
- cvec-1.5.2/examples/add_agent_post_example.py +52 -0
- cvec-1.5.2/examples/add_metric_data_arrow_example.py +34 -0
- cvec-1.5.2/examples/add_metric_data_example.py +34 -0
- cvec-1.5.2/examples/add_multiple_metrics_and_get_spans_for_them.py +127 -0
- cvec-1.5.2/examples/eav_example.py +29 -0
- cvec-1.5.2/examples/get_metric_arrow_example.py +26 -0
- cvec-1.5.2/examples/get_metric_data_objects_example.py +21 -0
- cvec-1.5.2/examples/get_metrics_example.py +20 -0
- cvec-1.5.2/examples/get_modeling_metrics_data_arrow_example.py +26 -0
- cvec-1.5.2/examples/get_modeling_metrics_data_example.py +33 -0
- cvec-1.5.2/examples/get_modeling_metrics_example.py +18 -0
- cvec-1.5.2/examples/get_spans_example.py +25 -0
- cvec-1.5.2/examples/show_eav_schema.py +27 -0
- {cvec-1.4.3 → cvec-1.5.2}/pyproject.toml +14 -12
- cvec-1.5.2/scripts/csv_import.py +228 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/cvec.py +89 -12
- cvec-1.5.2/src/cvec/http_cache.py +40 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/agent_post.py +1 -0
- cvec-1.5.2/tests/__init__.py +0 -0
- cvec-1.5.2/tests/test_cvec.py +899 -0
- cvec-1.5.2/tests/test_http_cache.py +407 -0
- cvec-1.5.2/tests/test_http_compression.py +226 -0
- cvec-1.5.2/tests/test_modeling.py +163 -0
- cvec-1.5.2/tests/test_token_refresh.py +162 -0
- cvec-1.5.2/uv.lock +519 -0
- {cvec-1.4.3 → cvec-1.5.2}/LICENSE +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/__init__.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/__init__.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/eav_column.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/eav_filter.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/eav_table.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/metric.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/models/span.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/py.typed +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/utils/__init__.py +0 -0
- {cvec-1.4.3 → cvec-1.5.2}/src/cvec/utils/arrow_converter.py +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "uv run python-claude session start"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"type": "command",
|
|
12
|
+
"command": "uv run python-claude git status"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"Stop": [
|
|
18
|
+
{
|
|
19
|
+
"hooks": [
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "uv run python-claude ruff format"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "uv run python-claude ruff check"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "uv run python-claude mypy"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "uv run python-claude pytest"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"PostToolUse": [
|
|
40
|
+
{
|
|
41
|
+
"matcher": "Write|Edit",
|
|
42
|
+
"hooks": [
|
|
43
|
+
{
|
|
44
|
+
"type": "command",
|
|
45
|
+
"command": "uv run python-claude edited"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(chmod:*)",
|
|
5
|
+
"Bash(python:*)",
|
|
6
|
+
"Bash(git commit:*)",
|
|
7
|
+
"Bash(pytest:*)",
|
|
8
|
+
"Bash(python3 -m pytest:*)",
|
|
9
|
+
"Bash(poetry run pytest:*)",
|
|
10
|
+
"Bash(git add:*)",
|
|
11
|
+
"Bash(poetry run mypy:*)",
|
|
12
|
+
"Bash(git checkout:*)",
|
|
13
|
+
"Bash(poetry run ruff:*)",
|
|
14
|
+
"Bash(poetry install:*)",
|
|
15
|
+
"Bash(tree:*)",
|
|
16
|
+
"Bash(git mv:*)",
|
|
17
|
+
"WebFetch(domain:github.com)",
|
|
18
|
+
"WebFetch(domain:pypi.org)",
|
|
19
|
+
"Bash(poetry run python:*)",
|
|
20
|
+
"Bash(poetry add:*)",
|
|
21
|
+
"Bash(git fetch:*)",
|
|
22
|
+
"Bash(git rebase:*)",
|
|
23
|
+
"Bash(git rm:*)"
|
|
24
|
+
],
|
|
25
|
+
"deny": [],
|
|
26
|
+
"ask": []
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Continuous Integration
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- .github/workflows/ci.yml
|
|
7
|
+
- uv.lock
|
|
8
|
+
- pyproject.toml
|
|
9
|
+
- src/**
|
|
10
|
+
- tests/**
|
|
11
|
+
push:
|
|
12
|
+
paths:
|
|
13
|
+
- .github/workflows/ci.yml
|
|
14
|
+
- uv.lock
|
|
15
|
+
- pyproject.toml
|
|
16
|
+
- src/**
|
|
17
|
+
- tests/**
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
runs-on: ubuntu-24.04
|
|
22
|
+
strategy:
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout
|
|
28
|
+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
29
|
+
|
|
30
|
+
- uses: CVector-Energy/python-test@uv
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python-version }}
|
|
33
|
+
src-dirs: .
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Python License Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
license-check:
|
|
8
|
+
runs-on: ubuntu-24.04
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
|
12
|
+
|
|
13
|
+
- name: Check Python licenses
|
|
14
|
+
uses: CVector-Energy/pyproject-license-check@main
|
|
15
|
+
with:
|
|
16
|
+
app-id: ${{ vars.APP_ID }}
|
|
17
|
+
app-private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Python License Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
license-check:
|
|
8
|
+
runs-on: ubuntu-24.04
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
|
12
|
+
|
|
13
|
+
- name: Check Python licenses
|
|
14
|
+
uses: CVector-Energy/pyproject-license-check@main
|
|
15
|
+
with:
|
|
16
|
+
app-id: ${{ vars.APP_ID }}
|
|
17
|
+
app-private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
cvec-1.5.2/.gitignore
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# Ruff stuff:
|
|
171
|
+
.ruff_cache/
|
|
172
|
+
|
|
173
|
+
# PyPI configuration file
|
|
174
|
+
.pypirc
|
|
175
|
+
.aider*
|
|
176
|
+
|
|
177
|
+
.vscode/
|
cvec-1.5.2/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- Name files for their main export, transforming Python names from PascalCase to underscore_case. For example, the file that defines the EAVFilter class should be named eav_filter.py.
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cvec
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.2
|
|
4
4
|
Summary: SDK for CVector Energy
|
|
5
|
+
Author-email: CVector <support@cvector.energy>
|
|
5
6
|
License-Expression: MIT
|
|
6
7
|
License-File: LICENSE
|
|
7
|
-
|
|
8
|
-
Author-email: support@cvector.energy
|
|
9
|
-
Requires-Python: >=3.10
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
10
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
-
Requires-
|
|
20
|
-
Requires-Dist:
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: brotli<2,>=1.2.0
|
|
19
|
+
Requires-Dist: pyarrow>=22.0.0
|
|
20
|
+
Requires-Dist: pydantic>=2.12.0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
|
|
23
23
|
# CVec Client Library
|
|
@@ -55,7 +55,7 @@ import cvec
|
|
|
55
55
|
from datetime import datetime
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Construct the CVec client. The host
|
|
58
|
+
Construct the CVec client. The host and api_key can be given through parameters to the constructor or from the environment variables CVEC_HOST and CVEC_API_KEY:
|
|
59
59
|
|
|
60
60
|
```
|
|
61
61
|
cvec = cvec.CVec()
|
|
@@ -110,7 +110,7 @@ mygroup/myedge/compressor01/motor/power_kw
|
|
|
110
110
|
|
|
111
111
|
### Metric Data
|
|
112
112
|
|
|
113
|
-
The main content for a metric is a set of points where the metric value changed. These are returned
|
|
113
|
+
The main content for a metric is a set of points where the metric value changed. These are returned with columns for name, time, value_double, value_string.
|
|
114
114
|
|
|
115
115
|
To get all of the value changes for all metrics at 10am on 2025-05-14, run:
|
|
116
116
|
|
|
@@ -136,6 +136,17 @@ Example output:
|
|
|
136
136
|
|
|
137
137
|
[46257 rows x 4 columns]
|
|
138
138
|
```
|
|
139
|
+
#### Pandas Data Frames
|
|
140
|
+
|
|
141
|
+
Use the `get_metric_arrow` function to efficiently load data into a pandas DataFrame like this:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
import pandas as pd
|
|
145
|
+
import pyarrow as pa
|
|
146
|
+
|
|
147
|
+
reader = pa.ipc.open_file(cvec.get_metric_arrow(names=["tag1", "tag2"]))
|
|
148
|
+
df = reader.read_pandas()
|
|
149
|
+
```
|
|
139
150
|
|
|
140
151
|
### Adding Metric Data
|
|
141
152
|
|
|
@@ -220,9 +231,9 @@ The script automatically:
|
|
|
220
231
|
|
|
221
232
|
The SDK provides an API client class named `CVec` with the following functions.
|
|
222
233
|
|
|
223
|
-
## `__init__(?host, ?
|
|
234
|
+
## `__init__(?host, ?api_key, ?default_start_at, ?default_end_at)`
|
|
224
235
|
|
|
225
|
-
Setup the SDK with the given host and API Key. The host and API key are loaded from environment variables CVEC_HOST
|
|
236
|
+
Setup the SDK with the given host and API Key. The host and API key are loaded from environment variables CVEC_HOST and CVEC_API_KEY if they are not given as arguments to the constructor. The tenant ID is automatically fetched from the host's `/config` endpoint. The `default_start_at` and `default_end_at` can provide a default query time interval for API methods.
|
|
226
237
|
|
|
227
238
|
## `get_spans(name, ?start_at, ?end_at, ?limit)`
|
|
228
239
|
|
|
@@ -284,3 +295,113 @@ Fetch actual data values from modeling metrics within a time range in Apache Arr
|
|
|
284
295
|
|
|
285
296
|
Returns Arrow IPC format data that can be read using `pyarrow.ipc.open_file()`.
|
|
286
297
|
|
|
298
|
+
## `get_eav_tables()`
|
|
299
|
+
|
|
300
|
+
Get all EAV (Entity-Attribute-Value) tables for the tenant. EAV tables store semi-structured data where each row represents an entity with flexible attributes.
|
|
301
|
+
|
|
302
|
+
Returns a list of `EAVTable` objects, each containing:
|
|
303
|
+
- `id`: The table's UUID
|
|
304
|
+
- `tenant_id`: The tenant ID
|
|
305
|
+
- `name`: Human-readable table name
|
|
306
|
+
- `created_at`: When the table was created
|
|
307
|
+
- `updated_at`: When the table was last updated
|
|
308
|
+
|
|
309
|
+
Example:
|
|
310
|
+
```python
|
|
311
|
+
tables = cvec.get_eav_tables()
|
|
312
|
+
for table in tables:
|
|
313
|
+
print(f"{table.name} (id: {table.id})")
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## `get_eav_columns(table_id)`
|
|
317
|
+
|
|
318
|
+
Get all columns for a specific EAV table.
|
|
319
|
+
|
|
320
|
+
- `table_id`: The UUID of the EAV table
|
|
321
|
+
|
|
322
|
+
Returns a list of `EAVColumn` objects, each containing:
|
|
323
|
+
- `eav_table_id`: The parent table's UUID
|
|
324
|
+
- `eav_column_id`: The column's ID (used for queries)
|
|
325
|
+
- `name`: Human-readable column name
|
|
326
|
+
- `type`: Data type (`"number"`, `"string"`, or `"boolean"`)
|
|
327
|
+
- `created_at`: When the column was created
|
|
328
|
+
|
|
329
|
+
Example:
|
|
330
|
+
```python
|
|
331
|
+
columns = cvec.get_eav_columns("00000000-0000-0000-0000-000000000000")
|
|
332
|
+
for column in columns:
|
|
333
|
+
print(f" {column.name} ({column.type}, id: {column.eav_column_id})")
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## `select_from_eav(table_name, ?column_names, ?filters)`
|
|
337
|
+
|
|
338
|
+
Query pivoted data from EAV tables using human-readable names. This is the recommended method for most use cases as it allows you to work with table and column names instead of UUIDs.
|
|
339
|
+
|
|
340
|
+
- `table_name`: Name of the EAV table to query
|
|
341
|
+
- `column_names`: Optional list of column names to include. If `None`, all columns are returned.
|
|
342
|
+
- `filters`: Optional list of `EAVFilter` objects to filter results
|
|
343
|
+
|
|
344
|
+
Each `EAVFilter` must use `column_name` and can specify:
|
|
345
|
+
- `column_name`: The column name to filter on (required)
|
|
346
|
+
- `numeric_min`: Minimum numeric value (inclusive)
|
|
347
|
+
- `numeric_max`: Maximum numeric value (exclusive)
|
|
348
|
+
- `string_value`: Exact string value to match
|
|
349
|
+
- `boolean_value`: Boolean value to match
|
|
350
|
+
|
|
351
|
+
Returns a list of dictionaries (maximum 1000 rows), each representing a row with an `id` field and fields for each requested column.
|
|
352
|
+
|
|
353
|
+
Example:
|
|
354
|
+
```python
|
|
355
|
+
from cvec import CVec, EAVFilter
|
|
356
|
+
|
|
357
|
+
# Query with filters
|
|
358
|
+
filters = [
|
|
359
|
+
EAVFilter(column_name="Weight", numeric_min=100, numeric_max=200),
|
|
360
|
+
EAVFilter(column_name="Status", string_value="ACTIVE"),
|
|
361
|
+
]
|
|
362
|
+
|
|
363
|
+
rows = cvec.select_from_eav(
|
|
364
|
+
table_name="Production Data",
|
|
365
|
+
column_names=["Date", "Weight", "Status"],
|
|
366
|
+
filters=filters,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
for row in rows:
|
|
370
|
+
print(row)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## `select_from_eav_id(table_id, ?column_ids, ?filters)`
|
|
374
|
+
|
|
375
|
+
Query pivoted data from EAV tables using table and column IDs directly. This is a lower-level method for cases where you already have the UUIDs and want to avoid name lookups.
|
|
376
|
+
|
|
377
|
+
- `table_id`: UUID of the EAV table to query
|
|
378
|
+
- `column_ids`: Optional list of column IDs to include. If `None`, all columns are returned.
|
|
379
|
+
- `filters`: Optional list of `EAVFilter` objects to filter results
|
|
380
|
+
|
|
381
|
+
Each `EAVFilter` must use `column_id` and can specify:
|
|
382
|
+
- `column_id`: The column ID to filter on (required)
|
|
383
|
+
- `numeric_min`: Minimum numeric value (inclusive)
|
|
384
|
+
- `numeric_max`: Maximum numeric value (exclusive)
|
|
385
|
+
- `string_value`: Exact string value to match
|
|
386
|
+
- `boolean_value`: Boolean value to match
|
|
387
|
+
|
|
388
|
+
Returns a list of dictionaries (up to 1000), each representing a row. Each row has a field for each column plus an `id` (the "row ID").
|
|
389
|
+
|
|
390
|
+
Example:
|
|
391
|
+
```python
|
|
392
|
+
from cvec import EAVFilter
|
|
393
|
+
|
|
394
|
+
filters = [
|
|
395
|
+
EAVFilter(column_id="abcd", numeric_min=100, numeric_max=200),
|
|
396
|
+
EAVFilter(column_id="efgh", string_value="ACTIVE"),
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
rows = cvec.select_from_eav_id(
|
|
400
|
+
table_id="00000000-0000-0000-0000-000000000000",
|
|
401
|
+
column_ids=["abcd", "efgh", "ijkl"],
|
|
402
|
+
filters=filters,
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
for row in rows:
|
|
406
|
+
print(f"ID: {row['id']}, Values: {row}")
|
|
407
|
+
```
|
|
@@ -33,7 +33,7 @@ import cvec
|
|
|
33
33
|
from datetime import datetime
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Construct the CVec client. The host
|
|
36
|
+
Construct the CVec client. The host and api_key can be given through parameters to the constructor or from the environment variables CVEC_HOST and CVEC_API_KEY:
|
|
37
37
|
|
|
38
38
|
```
|
|
39
39
|
cvec = cvec.CVec()
|
|
@@ -88,7 +88,7 @@ mygroup/myedge/compressor01/motor/power_kw
|
|
|
88
88
|
|
|
89
89
|
### Metric Data
|
|
90
90
|
|
|
91
|
-
The main content for a metric is a set of points where the metric value changed. These are returned
|
|
91
|
+
The main content for a metric is a set of points where the metric value changed. These are returned with columns for name, time, value_double, value_string.
|
|
92
92
|
|
|
93
93
|
To get all of the value changes for all metrics at 10am on 2025-05-14, run:
|
|
94
94
|
|
|
@@ -114,6 +114,17 @@ Example output:
|
|
|
114
114
|
|
|
115
115
|
[46257 rows x 4 columns]
|
|
116
116
|
```
|
|
117
|
+
#### Pandas Data Frames
|
|
118
|
+
|
|
119
|
+
Use the `get_metric_arrow` function to efficiently load data into a pandas DataFrame like this:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import pandas as pd
|
|
123
|
+
import pyarrow as pa
|
|
124
|
+
|
|
125
|
+
reader = pa.ipc.open_file(cvec.get_metric_arrow(names=["tag1", "tag2"]))
|
|
126
|
+
df = reader.read_pandas()
|
|
127
|
+
```
|
|
117
128
|
|
|
118
129
|
### Adding Metric Data
|
|
119
130
|
|
|
@@ -198,9 +209,9 @@ The script automatically:
|
|
|
198
209
|
|
|
199
210
|
The SDK provides an API client class named `CVec` with the following functions.
|
|
200
211
|
|
|
201
|
-
## `__init__(?host, ?
|
|
212
|
+
## `__init__(?host, ?api_key, ?default_start_at, ?default_end_at)`
|
|
202
213
|
|
|
203
|
-
Setup the SDK with the given host and API Key. The host and API key are loaded from environment variables CVEC_HOST
|
|
214
|
+
Setup the SDK with the given host and API Key. The host and API key are loaded from environment variables CVEC_HOST and CVEC_API_KEY if they are not given as arguments to the constructor. The tenant ID is automatically fetched from the host's `/config` endpoint. The `default_start_at` and `default_end_at` can provide a default query time interval for API methods.
|
|
204
215
|
|
|
205
216
|
## `get_spans(name, ?start_at, ?end_at, ?limit)`
|
|
206
217
|
|
|
@@ -261,3 +272,114 @@ Fetch actual data values from modeling metrics within a time range in Apache Arr
|
|
|
261
272
|
- `end_at`: Optional end time for the query (uses class default if not specified)
|
|
262
273
|
|
|
263
274
|
Returns Arrow IPC format data that can be read using `pyarrow.ipc.open_file()`.
|
|
275
|
+
|
|
276
|
+
## `get_eav_tables()`
|
|
277
|
+
|
|
278
|
+
Get all EAV (Entity-Attribute-Value) tables for the tenant. EAV tables store semi-structured data where each row represents an entity with flexible attributes.
|
|
279
|
+
|
|
280
|
+
Returns a list of `EAVTable` objects, each containing:
|
|
281
|
+
- `id`: The table's UUID
|
|
282
|
+
- `tenant_id`: The tenant ID
|
|
283
|
+
- `name`: Human-readable table name
|
|
284
|
+
- `created_at`: When the table was created
|
|
285
|
+
- `updated_at`: When the table was last updated
|
|
286
|
+
|
|
287
|
+
Example:
|
|
288
|
+
```python
|
|
289
|
+
tables = cvec.get_eav_tables()
|
|
290
|
+
for table in tables:
|
|
291
|
+
print(f"{table.name} (id: {table.id})")
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## `get_eav_columns(table_id)`
|
|
295
|
+
|
|
296
|
+
Get all columns for a specific EAV table.
|
|
297
|
+
|
|
298
|
+
- `table_id`: The UUID of the EAV table
|
|
299
|
+
|
|
300
|
+
Returns a list of `EAVColumn` objects, each containing:
|
|
301
|
+
- `eav_table_id`: The parent table's UUID
|
|
302
|
+
- `eav_column_id`: The column's ID (used for queries)
|
|
303
|
+
- `name`: Human-readable column name
|
|
304
|
+
- `type`: Data type (`"number"`, `"string"`, or `"boolean"`)
|
|
305
|
+
- `created_at`: When the column was created
|
|
306
|
+
|
|
307
|
+
Example:
|
|
308
|
+
```python
|
|
309
|
+
columns = cvec.get_eav_columns("00000000-0000-0000-0000-000000000000")
|
|
310
|
+
for column in columns:
|
|
311
|
+
print(f" {column.name} ({column.type}, id: {column.eav_column_id})")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## `select_from_eav(table_name, ?column_names, ?filters)`
|
|
315
|
+
|
|
316
|
+
Query pivoted data from EAV tables using human-readable names. This is the recommended method for most use cases as it allows you to work with table and column names instead of UUIDs.
|
|
317
|
+
|
|
318
|
+
- `table_name`: Name of the EAV table to query
|
|
319
|
+
- `column_names`: Optional list of column names to include. If `None`, all columns are returned.
|
|
320
|
+
- `filters`: Optional list of `EAVFilter` objects to filter results
|
|
321
|
+
|
|
322
|
+
Each `EAVFilter` must use `column_name` and can specify:
|
|
323
|
+
- `column_name`: The column name to filter on (required)
|
|
324
|
+
- `numeric_min`: Minimum numeric value (inclusive)
|
|
325
|
+
- `numeric_max`: Maximum numeric value (exclusive)
|
|
326
|
+
- `string_value`: Exact string value to match
|
|
327
|
+
- `boolean_value`: Boolean value to match
|
|
328
|
+
|
|
329
|
+
Returns a list of dictionaries (maximum 1000 rows), each representing a row with an `id` field and fields for each requested column.
|
|
330
|
+
|
|
331
|
+
Example:
|
|
332
|
+
```python
|
|
333
|
+
from cvec import CVec, EAVFilter
|
|
334
|
+
|
|
335
|
+
# Query with filters
|
|
336
|
+
filters = [
|
|
337
|
+
EAVFilter(column_name="Weight", numeric_min=100, numeric_max=200),
|
|
338
|
+
EAVFilter(column_name="Status", string_value="ACTIVE"),
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
rows = cvec.select_from_eav(
|
|
342
|
+
table_name="Production Data",
|
|
343
|
+
column_names=["Date", "Weight", "Status"],
|
|
344
|
+
filters=filters,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
for row in rows:
|
|
348
|
+
print(row)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## `select_from_eav_id(table_id, ?column_ids, ?filters)`
|
|
352
|
+
|
|
353
|
+
Query pivoted data from EAV tables using table and column IDs directly. This is a lower-level method for cases where you already have the UUIDs and want to avoid name lookups.
|
|
354
|
+
|
|
355
|
+
- `table_id`: UUID of the EAV table to query
|
|
356
|
+
- `column_ids`: Optional list of column IDs to include. If `None`, all columns are returned.
|
|
357
|
+
- `filters`: Optional list of `EAVFilter` objects to filter results
|
|
358
|
+
|
|
359
|
+
Each `EAVFilter` must use `column_id` and can specify:
|
|
360
|
+
- `column_id`: The column ID to filter on (required)
|
|
361
|
+
- `numeric_min`: Minimum numeric value (inclusive)
|
|
362
|
+
- `numeric_max`: Maximum numeric value (exclusive)
|
|
363
|
+
- `string_value`: Exact string value to match
|
|
364
|
+
- `boolean_value`: Boolean value to match
|
|
365
|
+
|
|
366
|
+
Returns a list of dictionaries (up to 1000), each representing a row. Each row has a field for each column plus an `id` (the "row ID").
|
|
367
|
+
|
|
368
|
+
Example:
|
|
369
|
+
```python
|
|
370
|
+
from cvec import EAVFilter
|
|
371
|
+
|
|
372
|
+
filters = [
|
|
373
|
+
EAVFilter(column_id="abcd", numeric_min=100, numeric_max=200),
|
|
374
|
+
EAVFilter(column_id="efgh", string_value="ACTIVE"),
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
rows = cvec.select_from_eav_id(
|
|
378
|
+
table_id="00000000-0000-0000-0000-000000000000",
|
|
379
|
+
column_ids=["abcd", "efgh", "ijkl"],
|
|
380
|
+
filters=filters,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
for row in rows:
|
|
384
|
+
print(f"ID: {row['id']}, Values: {row}")
|
|
385
|
+
```
|