varmeta 0.1.0__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.
- varmeta-0.1.0/.bumpversion.cfg +8 -0
- varmeta-0.1.0/.gitignore +10 -0
- varmeta-0.1.0/.pre-commit-config.yaml +11 -0
- varmeta-0.1.0/.python-version +1 -0
- varmeta-0.1.0/.vscode/settings.json +7 -0
- varmeta-0.1.0/LICENSE +21 -0
- varmeta-0.1.0/PKG-INFO +154 -0
- varmeta-0.1.0/README.md +143 -0
- varmeta-0.1.0/pyproject.toml +39 -0
- varmeta-0.1.0/src/varmeta/__init__.py +32 -0
- varmeta-0.1.0/src/varmeta/vars.py +304 -0
- varmeta-0.1.0/tests/test_doc_examples.py +89 -0
- varmeta-0.1.0/tests/test_vars.py +139 -0
- varmeta-0.1.0/tests/test_vars_json.py +38 -0
- varmeta-0.1.0/tests/test_vars_numpy.py +45 -0
- varmeta-0.1.0/tests/test_vars_pandas.py +187 -0
- varmeta-0.1.0/uv.lock +235 -0
varmeta-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# See https://pre-commit.com for more information
|
|
2
|
+
# See https://pre-commit.com/hooks.html for more hooks
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
5
|
+
# Ruff version.
|
|
6
|
+
rev: v0.11.9
|
|
7
|
+
hooks:
|
|
8
|
+
# Run the linter.
|
|
9
|
+
- id: ruff
|
|
10
|
+
# Run the formatter.
|
|
11
|
+
- id: ruff-format
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
varmeta-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Reuben Rusk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
varmeta-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: varmeta
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight variable metadata management.
|
|
5
|
+
Author-email: Reuben Rusk <pythoro@mindquip.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
|
+
Requires-Dist: numpy>=1.11.0
|
|
9
|
+
Requires-Dist: pandas>=2.3.1
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# varmeta
|
|
14
|
+
|
|
15
|
+
`varmeta` is a small and lightweight Python package for managing and using variable metadata in scientific, engineering, and data analysis workflows in outputs. It's designed with type safety in mind for use with modern IDEs like VSCode + pylance.
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
We often have variables with several components (e.g. x, y, and z components). We want to use them as lists or arrays, but tabulate them nicely for outputs. `varmeta` solves this problem in a simple way.
|
|
20
|
+
|
|
21
|
+
- Set up a dictionary of Var instances, with string keys.
|
|
22
|
+
- Set up matching dictionaries of data.
|
|
23
|
+
- Create pandas dataframes with nice multi-index headings containing not just the variable keys, but also their names and units, OR:
|
|
24
|
+
- Split variables into components automatically for other uses.
|
|
25
|
+
|
|
26
|
+
## Quick-start tutorial
|
|
27
|
+
|
|
28
|
+
### 1. Define variables with metadata
|
|
29
|
+
|
|
30
|
+
Let's first set up some imports, constants, and Var instances.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
import varmeta as vm
|
|
34
|
+
|
|
35
|
+
TEMP = "temperature"
|
|
36
|
+
FORCE = "force"
|
|
37
|
+
|
|
38
|
+
# Scalar variable
|
|
39
|
+
temperature = vm.Var(
|
|
40
|
+
key=TEMP,
|
|
41
|
+
name="Temperature",
|
|
42
|
+
units="Celsius",
|
|
43
|
+
desciption="Ambient temperature",
|
|
44
|
+
components=None
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Vector variable (e.g., 3D force)
|
|
48
|
+
force = vm.Var(
|
|
49
|
+
key=FORCE,
|
|
50
|
+
name="Force",
|
|
51
|
+
units="N",
|
|
52
|
+
desciption="Force vector",
|
|
53
|
+
components=("x", "y", "z"),
|
|
54
|
+
component_axis=1
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Use literal keys for Var and data dictionaries
|
|
59
|
+
|
|
60
|
+
Use shared literal string keys for dictionaries of Var instances and
|
|
61
|
+
data dictionaries.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
data_dct = {
|
|
65
|
+
TEMP: 25.0,
|
|
66
|
+
FORCE: [10.0, 20.0, 30.0]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var_dct = vm.VarDict({
|
|
70
|
+
TEMP: temperature,
|
|
71
|
+
FORCE: force
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Unpack data with components
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
vars, vals = vm.unpack(var_dct, data_dct)
|
|
79
|
+
print(vars)
|
|
80
|
+
# {'temp': Temperature [Celsius], 'force_x': Force - x [N], 'force_y': Force - y [N], 'force_z': Force - z [N]}
|
|
81
|
+
print(vals)
|
|
82
|
+
# {'temp': 25.0, 'force_x': 10.0, 'force_y': 20.0, 'force_z': 30.0}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 5. Tabulate dict-based data into pandas DataFrames
|
|
86
|
+
|
|
87
|
+
It's easy to tabulate data into a DataFrame. Data is automatically unpacked,
|
|
88
|
+
even numpy arrays!
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
data_dct = {FORCE: [[200, 250, -30], [300, 350, -100]], TEMP: [30, 40]}
|
|
92
|
+
df = vm.dict_to_df(var_dct, data_dct)
|
|
93
|
+
print(df)
|
|
94
|
+
# key force_x force_y force_z temp
|
|
95
|
+
# name Force - x Force - y Force - z Temperature
|
|
96
|
+
# units N N N Celsius
|
|
97
|
+
# 0 200 250 -30 30
|
|
98
|
+
# 1 300 350 -100 40
|
|
99
|
+
data_dct = {TEMP: [30, 40], FORCE: [[200, 250, -30], [300, 350, -100]]}
|
|
100
|
+
df = vm.dict_to_df(var_dct, data_dct)
|
|
101
|
+
print(df)
|
|
102
|
+
# key temp force_x force_y force_z
|
|
103
|
+
# name Temperature Force - x Force - y Force - z
|
|
104
|
+
# units Celsius N N N
|
|
105
|
+
# 0 30 200 250 -30
|
|
106
|
+
# 1 40 300 350 -100
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 6. Tabulate records easily
|
|
110
|
+
|
|
111
|
+
Say we'd had many records instead. We can make tables with lists of data
|
|
112
|
+
in dictionaries, unpacking each automatically, like this:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
data_dict_lst = [
|
|
116
|
+
{FORCE: [200, 250, -30], TEMP: 30},
|
|
117
|
+
{FORCE: [300, 350, -100], TEMP: 40},
|
|
118
|
+
]
|
|
119
|
+
df = vm.records_to_df(var_dct, data_dict_lst)
|
|
120
|
+
print(df)
|
|
121
|
+
# key force_x force_y force_z temp
|
|
122
|
+
# name Force - x Force - y Force - z Temperature
|
|
123
|
+
# units N N N Celsius
|
|
124
|
+
# 0 200 250 -30 30
|
|
125
|
+
# 1 300 350 -100 40
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Serialisation
|
|
129
|
+
|
|
130
|
+
We can convert to dictionaries like this:
|
|
131
|
+
```python
|
|
132
|
+
var_data = vm.vars_to_dict(var_dct)
|
|
133
|
+
print(var_data)
|
|
134
|
+
# Output
|
|
135
|
+
# {'temp': {'key': 'temp', 'name': 'Temperature', 'units': 'Celsius', 'desciption': 'Ambient temperature', 'components': None, 'component_axis': 0, 'data_type': 'object'}, 'force': {'key': 'force', 'name': 'Force', 'units': 'N', 'desciption': 'Force vector', 'components': ('x', 'y', 'z'), 'component_axis': 1, 'data_type': 'object'}}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Then we can convert back to Var instances like this:
|
|
139
|
+
```python
|
|
140
|
+
var_dct_recreated = vm.vars_from_dict(var_data)
|
|
141
|
+
for k, v in var_dct_recreated:
|
|
142
|
+
print(f"k: match is {v == var_dct[k]}")
|
|
143
|
+
# Output
|
|
144
|
+
# temp: match is True
|
|
145
|
+
# force: match is True
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The data (`var_data`) can be easily saved and read from JSON using the
|
|
149
|
+
standard *json* library.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
varmeta-0.1.0/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
|
|
2
|
+
# varmeta
|
|
3
|
+
|
|
4
|
+
`varmeta` is a small and lightweight Python package for managing and using variable metadata in scientific, engineering, and data analysis workflows in outputs. It's designed with type safety in mind for use with modern IDEs like VSCode + pylance.
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
We often have variables with several components (e.g. x, y, and z components). We want to use them as lists or arrays, but tabulate them nicely for outputs. `varmeta` solves this problem in a simple way.
|
|
9
|
+
|
|
10
|
+
- Set up a dictionary of Var instances, with string keys.
|
|
11
|
+
- Set up matching dictionaries of data.
|
|
12
|
+
- Create pandas dataframes with nice multi-index headings containing not just the variable keys, but also their names and units, OR:
|
|
13
|
+
- Split variables into components automatically for other uses.
|
|
14
|
+
|
|
15
|
+
## Quick-start tutorial
|
|
16
|
+
|
|
17
|
+
### 1. Define variables with metadata
|
|
18
|
+
|
|
19
|
+
Let's first set up some imports, constants, and Var instances.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import varmeta as vm
|
|
23
|
+
|
|
24
|
+
TEMP = "temperature"
|
|
25
|
+
FORCE = "force"
|
|
26
|
+
|
|
27
|
+
# Scalar variable
|
|
28
|
+
temperature = vm.Var(
|
|
29
|
+
key=TEMP,
|
|
30
|
+
name="Temperature",
|
|
31
|
+
units="Celsius",
|
|
32
|
+
desciption="Ambient temperature",
|
|
33
|
+
components=None
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Vector variable (e.g., 3D force)
|
|
37
|
+
force = vm.Var(
|
|
38
|
+
key=FORCE,
|
|
39
|
+
name="Force",
|
|
40
|
+
units="N",
|
|
41
|
+
desciption="Force vector",
|
|
42
|
+
components=("x", "y", "z"),
|
|
43
|
+
component_axis=1
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Use literal keys for Var and data dictionaries
|
|
48
|
+
|
|
49
|
+
Use shared literal string keys for dictionaries of Var instances and
|
|
50
|
+
data dictionaries.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
data_dct = {
|
|
54
|
+
TEMP: 25.0,
|
|
55
|
+
FORCE: [10.0, 20.0, 30.0]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var_dct = vm.VarDict({
|
|
59
|
+
TEMP: temperature,
|
|
60
|
+
FORCE: force
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Unpack data with components
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
vars, vals = vm.unpack(var_dct, data_dct)
|
|
68
|
+
print(vars)
|
|
69
|
+
# {'temp': Temperature [Celsius], 'force_x': Force - x [N], 'force_y': Force - y [N], 'force_z': Force - z [N]}
|
|
70
|
+
print(vals)
|
|
71
|
+
# {'temp': 25.0, 'force_x': 10.0, 'force_y': 20.0, 'force_z': 30.0}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 5. Tabulate dict-based data into pandas DataFrames
|
|
75
|
+
|
|
76
|
+
It's easy to tabulate data into a DataFrame. Data is automatically unpacked,
|
|
77
|
+
even numpy arrays!
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
data_dct = {FORCE: [[200, 250, -30], [300, 350, -100]], TEMP: [30, 40]}
|
|
81
|
+
df = vm.dict_to_df(var_dct, data_dct)
|
|
82
|
+
print(df)
|
|
83
|
+
# key force_x force_y force_z temp
|
|
84
|
+
# name Force - x Force - y Force - z Temperature
|
|
85
|
+
# units N N N Celsius
|
|
86
|
+
# 0 200 250 -30 30
|
|
87
|
+
# 1 300 350 -100 40
|
|
88
|
+
data_dct = {TEMP: [30, 40], FORCE: [[200, 250, -30], [300, 350, -100]]}
|
|
89
|
+
df = vm.dict_to_df(var_dct, data_dct)
|
|
90
|
+
print(df)
|
|
91
|
+
# key temp force_x force_y force_z
|
|
92
|
+
# name Temperature Force - x Force - y Force - z
|
|
93
|
+
# units Celsius N N N
|
|
94
|
+
# 0 30 200 250 -30
|
|
95
|
+
# 1 40 300 350 -100
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 6. Tabulate records easily
|
|
99
|
+
|
|
100
|
+
Say we'd had many records instead. We can make tables with lists of data
|
|
101
|
+
in dictionaries, unpacking each automatically, like this:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
data_dict_lst = [
|
|
105
|
+
{FORCE: [200, 250, -30], TEMP: 30},
|
|
106
|
+
{FORCE: [300, 350, -100], TEMP: 40},
|
|
107
|
+
]
|
|
108
|
+
df = vm.records_to_df(var_dct, data_dict_lst)
|
|
109
|
+
print(df)
|
|
110
|
+
# key force_x force_y force_z temp
|
|
111
|
+
# name Force - x Force - y Force - z Temperature
|
|
112
|
+
# units N N N Celsius
|
|
113
|
+
# 0 200 250 -30 30
|
|
114
|
+
# 1 300 350 -100 40
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Serialisation
|
|
118
|
+
|
|
119
|
+
We can convert to dictionaries like this:
|
|
120
|
+
```python
|
|
121
|
+
var_data = vm.vars_to_dict(var_dct)
|
|
122
|
+
print(var_data)
|
|
123
|
+
# Output
|
|
124
|
+
# {'temp': {'key': 'temp', 'name': 'Temperature', 'units': 'Celsius', 'desciption': 'Ambient temperature', 'components': None, 'component_axis': 0, 'data_type': 'object'}, 'force': {'key': 'force', 'name': 'Force', 'units': 'N', 'desciption': 'Force vector', 'components': ('x', 'y', 'z'), 'component_axis': 1, 'data_type': 'object'}}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Then we can convert back to Var instances like this:
|
|
128
|
+
```python
|
|
129
|
+
var_dct_recreated = vm.vars_from_dict(var_data)
|
|
130
|
+
for k, v in var_dct_recreated:
|
|
131
|
+
print(f"k: match is {v == var_dct[k]}")
|
|
132
|
+
# Output
|
|
133
|
+
# temp: match is True
|
|
134
|
+
# force: match is True
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The data (`var_data`) can be easily saved and read from JSON using the
|
|
138
|
+
standard *json* library.
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "varmeta"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Lightweight variable metadata management."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Reuben Rusk", email = "pythoro@mindquip.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"numpy>=1.11.0",
|
|
12
|
+
"pandas>=2.3.1",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
varmeta = "varmeta:main"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["hatchling"]
|
|
20
|
+
build-backend = "hatchling.build"
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"pytest>=8.4.1",
|
|
25
|
+
"ruff>=0.12.9",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.ruff]
|
|
29
|
+
line-length = 79
|
|
30
|
+
output-format = "concise"
|
|
31
|
+
|
|
32
|
+
[tool.ruff.lint]
|
|
33
|
+
select = ["E", "F", "B", "C90", "I", "UP", "SIM", "D", "ANN"]
|
|
34
|
+
|
|
35
|
+
[tool.ruff.lint.pydocstyle]
|
|
36
|
+
convention = "google"
|
|
37
|
+
|
|
38
|
+
[tool.ruff.lint.per-file-ignores]
|
|
39
|
+
"tests/*" = ["ANN", "D"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""varmeta: Lightweight variable metadata management for data workflows.
|
|
2
|
+
|
|
3
|
+
This package provides hashable variable objects with units, descriptions, and
|
|
4
|
+
component support, enabling robust metadata handling, serialization, and
|
|
5
|
+
integration with pandas and other tools.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
|
|
10
|
+
from .vars import (
|
|
11
|
+
Var,
|
|
12
|
+
VarData,
|
|
13
|
+
VarDict,
|
|
14
|
+
dict_to_df,
|
|
15
|
+
records_to_df,
|
|
16
|
+
unpack,
|
|
17
|
+
vars_from_dict,
|
|
18
|
+
vars_to_dict,
|
|
19
|
+
vars_to_multi_index_data,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Var",
|
|
24
|
+
"vars_to_multi_index_data",
|
|
25
|
+
"dict_to_df",
|
|
26
|
+
"VarData",
|
|
27
|
+
"VarDict",
|
|
28
|
+
"records_to_df",
|
|
29
|
+
"unpack",
|
|
30
|
+
"vars_to_dict",
|
|
31
|
+
"vars_from_dict",
|
|
32
|
+
]
|