rune-runtime 2.2.1__tar.gz → 2.2.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.
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/CODE_OF_CONDUCT.md +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/ISSUE_TEMPLATE/Bug_report.md +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/ISSUE_TEMPLATE/Feature_request.md +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/ISSUE_TEMPLATE/Support_question.md +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/ISSUE_TEMPLATE/meeting-minutes.md +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/workflows/build-python-package.yml +4 -0
- rune_runtime-2.2.2/.github/workflows/check-license-headers.yml +39 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/workflows/cve-scanning-python.yml +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/workflows/license-scanning-python.yml +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/workflows/release.yml +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.github/workflows/run-tests.yml +8 -0
- rune_runtime-2.2.2/.pre-commit-config.yaml +25 -0
- {rune_runtime-2.2.1/src/rune_runtime.egg-info → rune_runtime-2.2.2}/PKG-INFO +17 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/README.md +14 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/build_wheel.sh +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/dev_clean_setup.sh +6 -0
- rune_runtime-2.2.2/netlify.toml +6 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/pyproject.toml +7 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/safety-policy.yml +4 -0
- rune_runtime-2.2.2/src/license/apply_headers.sh +6 -0
- rune_runtime-2.2.2/src/license/header.txt +2 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/base_data_class.py +1 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/metadata.py +28 -27
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/version.py +3 -3
- {rune_runtime-2.2.1 → rune_runtime-2.2.2/src/rune_runtime.egg-info}/PKG-INFO +17 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune_runtime.egg-info/SOURCES.txt +4 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune_runtime.egg-info/requires.txt +2 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune_runtime.egg-info/scm_file_list.json +4 -0
- rune_runtime-2.2.2/src/rune_runtime.egg-info/scm_version.json +8 -0
- rune_runtime-2.2.2/src/rune_runtime.egg-info/top_level.txt +2 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_basic_types_with_meta.py +1 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_keys_and_references.py +57 -3
- rune_runtime-2.2.1/netlify.toml +0 -2
- rune_runtime-2.2.1/src/rune_runtime.egg-info/scm_version.json +0 -8
- rune_runtime-2.2.1/src/rune_runtime.egg-info/top_level.txt +0 -1
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.gitignore +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/.vscode/settings.json +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/CONTRIBUTING.md +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/EASYCLA_CHANGEME.md +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/LICENSE +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/LICENSE.spdx +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/MAINTAINERS.md +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/NOTICE +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/docs/home.md +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/renovate.json +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/setup.cfg +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/__init__.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/conditions.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/cow.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/extensions/__init__.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/extensions/cached_json_rune_object_deserializer.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/func_proxy.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/native_registry.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/object_builder.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/object_registry.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/py.typed +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune/runtime/utils.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/src/rune_runtime.egg-info/dependency_links.txt +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/__init__.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/cdm/EUR-Vanilla-account.json +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/cdm/test_create_irs.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/cdm/test_trade_creation.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/cdm/test_validation.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/_bundle.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/base/math/Abs.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/base/math/RoundToNearest.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/base/math/RoundingModeEnum.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/test_native_registry.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/test_simple.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/local_data/ird-ex01-vanilla-swap-versioned.json +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/run_runtime_tests.sh +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_basic.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_conditions.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_enumtype.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_extension.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_metakey.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_metalocation.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/serializer-round-trip/test_metascheme.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_cached_json_rune_object_deserializer.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_complex_types_with_meta.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_cow.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_deep_keys_and_references.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_deferred_ref_deserialization.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_func_proxy.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_list_cardinality_with_meta.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_namespace_prefix.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_object_builder.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_operations.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_parametrized_basic_types.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_rune_parent.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_rune_str.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_subtype_identity.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_utils.py +0 -0
- {rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/test_zoned_date_time.py +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
##
|
|
2
|
+
## Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
3
|
+
## SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
##
|
|
5
|
+
name: Check License Headers
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
- develop
|
|
12
|
+
pull_request:
|
|
13
|
+
branches:
|
|
14
|
+
- main
|
|
15
|
+
- develop
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
license-headers:
|
|
19
|
+
name: Verify license headers
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout repository
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Python 3.11
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: '3.11'
|
|
30
|
+
|
|
31
|
+
- name: Install licenseheaders
|
|
32
|
+
run: pip install licenseheaders
|
|
33
|
+
|
|
34
|
+
- name: Check license headers
|
|
35
|
+
run: |
|
|
36
|
+
src/license/apply_headers.sh
|
|
37
|
+
git diff --exit-code || \
|
|
38
|
+
(echo "One or more files are missing a license header. Run 'src/license/apply_headers.sh' locally to fix." && \
|
|
39
|
+
exit 1)
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
##
|
|
2
|
+
## Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
3
|
+
## SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
##
|
|
1
5
|
name: Run Unit Tests
|
|
2
6
|
|
|
3
7
|
on:
|
|
@@ -5,6 +9,10 @@ on:
|
|
|
5
9
|
branches:
|
|
6
10
|
- main
|
|
7
11
|
- develop
|
|
12
|
+
pull_request:
|
|
13
|
+
branches:
|
|
14
|
+
- main
|
|
15
|
+
- develop
|
|
8
16
|
|
|
9
17
|
jobs:
|
|
10
18
|
test:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
##
|
|
2
|
+
## Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
3
|
+
## SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
##
|
|
5
|
+
repos:
|
|
6
|
+
- repo: local
|
|
7
|
+
hooks:
|
|
8
|
+
- id: license-headers-dirs
|
|
9
|
+
name: Add/check license headers (src, test, .github)
|
|
10
|
+
entry: licenseheaders
|
|
11
|
+
args: [-t, src/license/header.txt, --dir, src, --dir, test, --dir, .github]
|
|
12
|
+
language: python
|
|
13
|
+
additional_dependencies: [licenseheaders>=0.8.8]
|
|
14
|
+
types_or: [python, yaml, shell, toml]
|
|
15
|
+
pass_filenames: false
|
|
16
|
+
- id: license-headers-files
|
|
17
|
+
name: Add/check license headers (root files)
|
|
18
|
+
entry: licenseheaders
|
|
19
|
+
args: [-t, src/license/header.txt, --additional-extensions, python=.toml,
|
|
20
|
+
-f, build_wheel.sh, dev_clean_setup.sh, netlify.toml, pyproject.toml,
|
|
21
|
+
safety-policy.yml, .pre-commit-config.yaml]
|
|
22
|
+
language: python
|
|
23
|
+
additional_dependencies: [licenseheaders>=0.8.8]
|
|
24
|
+
types_or: [python, yaml, shell, toml]
|
|
25
|
+
pass_filenames: false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rune-runtime
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: rune-runtime: the Rune DSL runtime for Python
|
|
5
5
|
Author: Daniel Schwartz, Plamen Neykov, Others (See AUTHORS)
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -30,6 +30,8 @@ Requires-Dist: pytest>=9.0.2; extra == "dev"
|
|
|
30
30
|
Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
|
|
31
31
|
Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
|
|
32
32
|
Requires-Dist: types-python-dateutil>=2.9.0.20250809; extra == "dev"
|
|
33
|
+
Requires-Dist: licenseheaders>=0.8.8; extra == "dev"
|
|
34
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
33
35
|
Dynamic: license-file
|
|
34
36
|
|
|
35
37
|
[](https://community.finos.org/docs/governance/Software-Projects/stages/incubating)
|
|
@@ -59,6 +61,20 @@ Use [dev_clean_setup.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/m
|
|
|
59
61
|
```sh
|
|
60
62
|
./dev_clean_setup.sh
|
|
61
63
|
```
|
|
64
|
+
|
|
65
|
+
This script installs all dev dependencies and registers the pre-commit hooks, including the license-header check. Every `.py` file under `src/` and `test/` must carry the Apache 2.0 SPDX header:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
69
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
To add missing headers to all files at any time, run:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
src/license/apply_headers.sh
|
|
76
|
+
```
|
|
77
|
+
|
|
62
78
|
### 3. Build
|
|
63
79
|
Use [build_wheel.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/main/build_wheel.sh) to build the package
|
|
64
80
|
```sh
|
|
@@ -25,6 +25,20 @@ Use [dev_clean_setup.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/m
|
|
|
25
25
|
```sh
|
|
26
26
|
./dev_clean_setup.sh
|
|
27
27
|
```
|
|
28
|
+
|
|
29
|
+
This script installs all dev dependencies and registers the pre-commit hooks, including the license-header check. Every `.py` file under `src/` and `test/` must carry the Apache 2.0 SPDX header:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
# Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
33
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
To add missing headers to all files at any time, run:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
src/license/apply_headers.sh
|
|
40
|
+
```
|
|
41
|
+
|
|
28
42
|
### 3. Build
|
|
29
43
|
Use [build_wheel.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/main/build_wheel.sh) to build the package
|
|
30
44
|
```sh
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
##
|
|
3
|
+
## Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
4
|
+
## SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
##
|
|
2
6
|
|
|
3
7
|
function error
|
|
4
8
|
{
|
|
@@ -34,3 +38,5 @@ ${PY_EXE} -m venv --clear .pydevenv || error
|
|
|
34
38
|
|
|
35
39
|
|
|
36
40
|
python -m pip install -e .[dev] --config-settings editable_mode=compat || error
|
|
41
|
+
|
|
42
|
+
pre-commit install || error
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
1
5
|
[build-system]
|
|
2
6
|
requires = ["setuptools>=64", "setuptools_scm>=8", "wheel>=0.45.1", "pytest-runner>=6.0.1"]
|
|
3
7
|
build-backend = "setuptools.build_meta"
|
|
@@ -15,7 +19,9 @@ optional-dependencies.dev = [
|
|
|
15
19
|
"pytest>=9.0.2",
|
|
16
20
|
"pytest-cov>=7.0.0",
|
|
17
21
|
"pytest-mock>=3.14.1",
|
|
18
|
-
"types-python-dateutil>=2.9.0.20250809"
|
|
22
|
+
"types-python-dateutil>=2.9.0.20250809",
|
|
23
|
+
"licenseheaders>=0.8.8",
|
|
24
|
+
"pre-commit>=3.0.0"
|
|
19
25
|
]
|
|
20
26
|
description = "rune-runtime: the Rune DSL runtime for Python"
|
|
21
27
|
readme = "README.md"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Applies the Apache 2.0 SPDX license header to all tracked source files.
|
|
3
|
+
set -e
|
|
4
|
+
TMPL="$(dirname "$0")/header.txt"
|
|
5
|
+
licenseheaders -t "$TMPL" --dir src --dir test --dir .github
|
|
6
|
+
licenseheaders -t "$TMPL" --additional-extensions python=.toml -f build_wheel.sh dev_clean_setup.sh netlify.toml pyproject.toml safety-policy.yml .pre-commit-config.yaml
|
|
@@ -107,7 +107,7 @@ class BaseDataClass(BaseModel, ComplexTypeMetaDataMixin):
|
|
|
107
107
|
@model_serializer(mode='wrap')
|
|
108
108
|
def _serialize_refs(self, serializer, info):
|
|
109
109
|
'''should replace objects with refs while serializing'''
|
|
110
|
-
res = serializer(self
|
|
110
|
+
res = serializer(self)
|
|
111
111
|
refs = self._get_rune_refs_container()
|
|
112
112
|
for property_nm, (key, ref_type) in refs.items():
|
|
113
113
|
res[property_nm] = {ref_type.rune_ref_tag: key}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'''Classes representing annotated basic Rune types'''
|
|
2
|
-
import uuid
|
|
3
2
|
import datetime
|
|
4
3
|
import importlib
|
|
5
|
-
|
|
6
|
-
from
|
|
4
|
+
import uuid
|
|
5
|
+
from collections.abc import Iterable
|
|
7
6
|
from decimal import Decimal
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from functools import lru_cache, partial
|
|
9
|
+
from typing import Any, Never, Self, get_args
|
|
10
|
+
|
|
11
|
+
from pydantic import PlainSerializer, PlainValidator, WrapSerializer, WrapValidator
|
|
12
12
|
from pydantic_core import PydanticCustomError
|
|
13
|
+
|
|
13
14
|
# from rune.runtime.object_registry import get_object
|
|
14
15
|
|
|
15
16
|
DEFAULT_META = '_ALLOWED_METADATA'
|
|
@@ -135,7 +136,7 @@ class Reference(BaseReference):
|
|
|
135
136
|
class UnresolvedReference(BaseReference):
|
|
136
137
|
'''used by the deserialization to hold temporarily unresolved references'''
|
|
137
138
|
def __init__(self, key):
|
|
138
|
-
rune_type, self.key =
|
|
139
|
+
rune_type, self.key = next(iter(key.items()))
|
|
139
140
|
self.key_type = KeyType.from_rune(rune_type)
|
|
140
141
|
|
|
141
142
|
def get_reference(self, parent):
|
|
@@ -219,7 +220,7 @@ class BaseMetaDataMixin:
|
|
|
219
220
|
self.set_meta(key=key)
|
|
220
221
|
try:
|
|
221
222
|
self._get_object_map(KeyType.INTERNAL)[key] = self
|
|
222
|
-
except:
|
|
223
|
+
except:
|
|
223
224
|
self.set_meta(key=None)
|
|
224
225
|
raise
|
|
225
226
|
return key
|
|
@@ -238,7 +239,7 @@ class BaseMetaDataMixin:
|
|
|
238
239
|
self.set_meta(check_allowed=True, **{key_type.key_tag: key})
|
|
239
240
|
try:
|
|
240
241
|
self._get_object_map(key_type)[key] = self
|
|
241
|
-
except:
|
|
242
|
+
except:
|
|
242
243
|
self.set_meta(check_allowed=True, **{key_type.key_tag: None})
|
|
243
244
|
raise
|
|
244
245
|
return self
|
|
@@ -298,13 +299,14 @@ class BaseMetaDataMixin:
|
|
|
298
299
|
f'not allowed for {property_nm}. Allowed types '
|
|
299
300
|
f'are: {allowed_ref_types.get(property_nm, {})}')
|
|
300
301
|
|
|
301
|
-
|
|
302
|
+
# Pydantic includes inherited fields and resolves their annotations.
|
|
303
|
+
field_type = type(self).model_fields[property_nm].annotation # type: ignore
|
|
302
304
|
allowed_type = _get_basic_type(field_type)
|
|
303
305
|
if not (isinstance(allowed_type, str)
|
|
304
306
|
or isinstance(ref.target, allowed_type)):
|
|
305
|
-
raise
|
|
306
|
-
|
|
307
|
-
|
|
307
|
+
raise TypeError("Can't set reference. Incompatible types: "
|
|
308
|
+
f"expected {allowed_type}, "
|
|
309
|
+
f"got {ref.target.__class__}")
|
|
308
310
|
|
|
309
311
|
refs = self.__dict__.setdefault(REFS_CONTAINER, {})
|
|
310
312
|
if property_nm not in refs:
|
|
@@ -416,9 +418,8 @@ class ComplexTypeMetaDataMixin(BaseMetaDataMixin):
|
|
|
416
418
|
prefix = namespace_prefix
|
|
417
419
|
if prefix is None:
|
|
418
420
|
prefix = cls._get_rune_namespace_prefix()
|
|
419
|
-
if prefix:
|
|
420
|
-
|
|
421
|
-
import_path = prefix + '.' + rune_type
|
|
421
|
+
if prefix and not rune_type.startswith(prefix + '.'):
|
|
422
|
+
import_path = prefix + '.' + rune_type
|
|
422
423
|
rune_module = importlib.import_module(import_path)
|
|
423
424
|
return getattr(rune_module, rune_class_name)
|
|
424
425
|
return cls # support for legacy json
|
|
@@ -453,14 +454,14 @@ class ComplexTypeMetaDataMixin(BaseMetaDataMixin):
|
|
|
453
454
|
'Expected either {my_type} or dict but '
|
|
454
455
|
'got {type}.',
|
|
455
456
|
{'type': type(obj), 'my_type': cls})
|
|
456
|
-
metadata = {k: obj[k] for k in obj
|
|
457
|
+
metadata = {k: obj[k] for k in obj if k.startswith('@')}
|
|
457
458
|
|
|
458
459
|
# References deserialization treatment
|
|
459
460
|
if aux := cls._create_unresolved_ref(metadata):
|
|
460
461
|
return aux
|
|
461
462
|
|
|
462
463
|
# Model creation
|
|
463
|
-
for k in metadata
|
|
464
|
+
for k in metadata:
|
|
464
465
|
obj.pop(k)
|
|
465
466
|
|
|
466
467
|
rune_cls = cls._type_to_cls(metadata)
|
|
@@ -483,7 +484,7 @@ class ComplexTypeMetaDataMixin(BaseMetaDataMixin):
|
|
|
483
484
|
|
|
484
485
|
@classmethod
|
|
485
486
|
@lru_cache
|
|
486
|
-
def validator(cls, allowed_meta: tuple[str] | tuple[Never, ...] =
|
|
487
|
+
def validator(cls, allowed_meta: tuple[str] | tuple[Never, ...] = ()):
|
|
487
488
|
'''default validator for the specific class'''
|
|
488
489
|
allowed = set(allowed_meta)
|
|
489
490
|
return PlainValidator(partial(cls.deserialize, allowed_meta=allowed),
|
|
@@ -492,16 +493,16 @@ class ComplexTypeMetaDataMixin(BaseMetaDataMixin):
|
|
|
492
493
|
|
|
493
494
|
class BasicTypeMetaDataMixin(BaseMetaDataMixin):
|
|
494
495
|
'''holds the metadata associated with an instance'''
|
|
495
|
-
_INPUT_TYPES: Any |
|
|
496
|
+
_INPUT_TYPES: Any | tuple[Any, ...] = str # to be overridden by subclasses
|
|
496
497
|
_OUTPUT_TYPE: Any = str # to be overridden by subclasses
|
|
497
498
|
_JSON_OUTPUT = str | dict
|
|
498
499
|
|
|
499
500
|
@classmethod
|
|
500
501
|
def _check_type(cls, value):
|
|
501
502
|
if not isinstance(value, cls._INPUT_TYPES):
|
|
502
|
-
raise
|
|
503
|
-
|
|
504
|
-
|
|
503
|
+
raise TypeError(f'{cls.__name__} can be instantiated only with '
|
|
504
|
+
f'one of the following type(s): {cls._INPUT_TYPES},'
|
|
505
|
+
f' however the value is of type {type(value)}')
|
|
505
506
|
|
|
506
507
|
@classmethod
|
|
507
508
|
def serialise(cls, obj, base_type) -> dict:
|
|
@@ -514,7 +515,7 @@ class BasicTypeMetaDataMixin(BaseMetaDataMixin):
|
|
|
514
515
|
def deserialize(cls, obj, handler, base_types, allowed_meta: set[str]):
|
|
515
516
|
'''method used as pydantic `validator`'''
|
|
516
517
|
if isinstance(obj, list):
|
|
517
|
-
identity = lambda x: x
|
|
518
|
+
identity = lambda x: x
|
|
518
519
|
processed = [cls.deserialize(item, identity, base_types, allowed_meta) for item in obj]
|
|
519
520
|
return handler(processed)
|
|
520
521
|
model = obj
|
|
@@ -649,7 +650,7 @@ class _EnumWrapper(BaseMetaDataMixin):
|
|
|
649
650
|
'''wrapper for enums with metadata'''
|
|
650
651
|
def __init__(self, enum_instance=_EnumWrapperDefaultVal.NOT_SET):
|
|
651
652
|
if not isinstance(enum_instance, Enum):
|
|
652
|
-
raise
|
|
653
|
+
raise TypeError("enum_instance must be an instance of an Enum")
|
|
653
654
|
self._enum_instance = enum_instance
|
|
654
655
|
|
|
655
656
|
@property
|
|
@@ -723,7 +724,7 @@ class EnumWithMetaMixin:
|
|
|
723
724
|
|
|
724
725
|
@classmethod
|
|
725
726
|
@lru_cache
|
|
726
|
-
def validator(cls, allowed_meta: tuple[str] | tuple[Never, ...] =
|
|
727
|
+
def validator(cls, allowed_meta: tuple[str] | tuple[Never, ...] = ()):
|
|
727
728
|
'''default validator for the specific class'''
|
|
728
729
|
allowed = set(allowed_meta)
|
|
729
730
|
return PlainValidator(partial(cls.deserialize, allowed_meta=allowed),
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 2,
|
|
21
|
+
__version__ = version = '2.2.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 2, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g951f0332c'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rune-runtime
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: rune-runtime: the Rune DSL runtime for Python
|
|
5
5
|
Author: Daniel Schwartz, Plamen Neykov, Others (See AUTHORS)
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -30,6 +30,8 @@ Requires-Dist: pytest>=9.0.2; extra == "dev"
|
|
|
30
30
|
Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
|
|
31
31
|
Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
|
|
32
32
|
Requires-Dist: types-python-dateutil>=2.9.0.20250809; extra == "dev"
|
|
33
|
+
Requires-Dist: licenseheaders>=0.8.8; extra == "dev"
|
|
34
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
33
35
|
Dynamic: license-file
|
|
34
36
|
|
|
35
37
|
[](https://community.finos.org/docs/governance/Software-Projects/stages/incubating)
|
|
@@ -59,6 +61,20 @@ Use [dev_clean_setup.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/m
|
|
|
59
61
|
```sh
|
|
60
62
|
./dev_clean_setup.sh
|
|
61
63
|
```
|
|
64
|
+
|
|
65
|
+
This script installs all dev dependencies and registers the pre-commit hooks, including the license-header check. Every `.py` file under `src/` and `test/` must carry the Apache 2.0 SPDX header:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Copyright (c) 2023-2026 CLOUDRISK Limited and FT Advisory LLC
|
|
69
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
To add missing headers to all files at any time, run:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
src/license/apply_headers.sh
|
|
76
|
+
```
|
|
77
|
+
|
|
62
78
|
### 3. Build
|
|
63
79
|
Use [build_wheel.sh](https://github.com/Cloudrisk/rune-python-runtime/blob/main/build_wheel.sh) to build the package
|
|
64
80
|
```sh
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
.gitignore
|
|
2
|
+
.pre-commit-config.yaml
|
|
2
3
|
CONTRIBUTING.md
|
|
3
4
|
EASYCLA_CHANGEME.md
|
|
4
5
|
LICENSE
|
|
@@ -18,12 +19,15 @@ safety-policy.yml
|
|
|
18
19
|
.github/ISSUE_TEMPLATE/Support_question.md
|
|
19
20
|
.github/ISSUE_TEMPLATE/meeting-minutes.md
|
|
20
21
|
.github/workflows/build-python-package.yml
|
|
22
|
+
.github/workflows/check-license-headers.yml
|
|
21
23
|
.github/workflows/cve-scanning-python.yml
|
|
22
24
|
.github/workflows/license-scanning-python.yml
|
|
23
25
|
.github/workflows/release.yml
|
|
24
26
|
.github/workflows/run-tests.yml
|
|
25
27
|
.vscode/settings.json
|
|
26
28
|
docs/home.md
|
|
29
|
+
src/license/apply_headers.sh
|
|
30
|
+
src/license/header.txt
|
|
27
31
|
src/rune/runtime/__init__.py
|
|
28
32
|
src/rune/runtime/base_data_class.py
|
|
29
33
|
src/rune/runtime/conditions.py
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
".github/ISSUE_TEMPLATE/Support_question.md",
|
|
7
7
|
".github/ISSUE_TEMPLATE/meeting-minutes.md",
|
|
8
8
|
".github/workflows/build-python-package.yml",
|
|
9
|
+
".github/workflows/check-license-headers.yml",
|
|
9
10
|
".github/workflows/cve-scanning-python.yml",
|
|
10
11
|
".github/workflows/license-scanning-python.yml",
|
|
11
12
|
".github/workflows/release.yml",
|
|
12
13
|
".github/workflows/run-tests.yml",
|
|
13
14
|
".gitignore",
|
|
15
|
+
".pre-commit-config.yaml",
|
|
14
16
|
".vscode/settings.json",
|
|
15
17
|
"CONTRIBUTING.md",
|
|
16
18
|
"EASYCLA_CHANGEME.md",
|
|
@@ -26,6 +28,8 @@
|
|
|
26
28
|
"pyproject.toml",
|
|
27
29
|
"renovate.json",
|
|
28
30
|
"safety-policy.yml",
|
|
31
|
+
"src/license/apply_headers.sh",
|
|
32
|
+
"src/license/header.txt",
|
|
29
33
|
"src/rune/runtime/__init__.py",
|
|
30
34
|
"src/rune/runtime/base_data_class.py",
|
|
31
35
|
"src/rune/runtime/conditions.py",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'''test key generation/retrieval runtime functions'''
|
|
2
|
+
import json
|
|
2
3
|
from decimal import Decimal
|
|
3
4
|
from typing_extensions import Annotated
|
|
4
5
|
import pytest
|
|
@@ -62,6 +63,23 @@ class DummyLoan2(BaseDataClass):
|
|
|
62
63
|
'repayment': {'@ref', '@ref:external'}
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
|
|
67
|
+
class NamedLoan(DummyLoan2):
|
|
68
|
+
'''Inherit both reference fields without redeclaring their annotations.'''
|
|
69
|
+
label: str = 'loan'
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ExtendedNamedLoan(NamedLoan):
|
|
73
|
+
'''Reference fields can be inherited through multiple levels.'''
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class LoanBook(BaseDataClass):
|
|
78
|
+
'''Key targets and inherited references in separate list fields.'''
|
|
79
|
+
cashflows: list[CashFlow]
|
|
80
|
+
loans: list[NamedLoan]
|
|
81
|
+
|
|
82
|
+
|
|
65
83
|
class DummyLoan3(BaseDataClass):
|
|
66
84
|
'''number test class'''
|
|
67
85
|
loan: Annotated[NumberWithMeta,
|
|
@@ -220,6 +238,38 @@ def test_ref_assign():
|
|
|
220
238
|
assert id(model.loan) == id(model.repayment)
|
|
221
239
|
|
|
222
240
|
|
|
241
|
+
@pytest.mark.parametrize('model_type', [NamedLoan, ExtendedNamedLoan])
|
|
242
|
+
def test_ref_assign_to_inherited_field(model_type):
|
|
243
|
+
'''Inherited reference fields retain their declared target type.'''
|
|
244
|
+
model = model_type(loan=CashFlow(currency='EUR', amount=100),
|
|
245
|
+
repayment=CashFlow(currency='EUR', amount=101))
|
|
246
|
+
|
|
247
|
+
model.repayment = Reference(model.loan)
|
|
248
|
+
|
|
249
|
+
assert model.repayment is model.loan
|
|
250
|
+
assert model.resolve_ref_key('repayment') == model.loan.get_meta('@key')
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@pytest.mark.parametrize('validate_model', [False, True])
|
|
254
|
+
def test_deserialize_inherited_references_in_lists(validate_model):
|
|
255
|
+
'''Inherited references resolve before optional model validation.'''
|
|
256
|
+
data = json.dumps({
|
|
257
|
+
'cashflows': [{
|
|
258
|
+
'@key:external': 'cashflow1', 'currency': 'EUR', 'amount': '100',
|
|
259
|
+
}],
|
|
260
|
+
'loans': [{
|
|
261
|
+
'loan': {'@ref:external': 'cashflow1'},
|
|
262
|
+
'repayment': {'@ref:external': 'cashflow1'},
|
|
263
|
+
}],
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
book = LoanBook.rune_deserialize(data, validate_model=validate_model)
|
|
267
|
+
|
|
268
|
+
assert book.loans[0].loan is book.cashflows[0]
|
|
269
|
+
assert book.loans[0].repayment is book.cashflows[0]
|
|
270
|
+
assert book.loans[0].resolve_ref_key('repayment') == 'cashflow1'
|
|
271
|
+
|
|
272
|
+
|
|
223
273
|
def test_ref_assign_from_cow_wrapped_object():
|
|
224
274
|
'''test use a ref from a COW-wrapped object'''
|
|
225
275
|
model = DummyLoan2(loan=CashFlow(currency='EUR', amount=100),
|
|
@@ -445,13 +495,17 @@ def test_reference_non_metadata_target_with_ext_key_raises():
|
|
|
445
495
|
Reference('not_an_object', 'ext_key')
|
|
446
496
|
|
|
447
497
|
|
|
448
|
-
|
|
498
|
+
@pytest.mark.parametrize('model_type', [DummyLoan2, NamedLoan, ExtendedNamedLoan])
|
|
499
|
+
def test_bind_property_rejects_wrong_type(model_type):
|
|
449
500
|
'''reject refs that don't match field type'''
|
|
450
|
-
model =
|
|
501
|
+
model = model_type(loan=CashFlow(currency='EUR', amount=100),
|
|
451
502
|
repayment=CashFlow(currency='EUR', amount=101))
|
|
503
|
+
original_repayment = model.repayment
|
|
452
504
|
other = OtherThing(name='other')
|
|
453
|
-
with pytest.raises(
|
|
505
|
+
with pytest.raises(TypeError, match='Incompatible types'):
|
|
454
506
|
model.repayment = Reference(other)
|
|
507
|
+
assert model.repayment is original_repayment
|
|
508
|
+
assert model.resolve_ref_key('repayment') is None
|
|
455
509
|
|
|
456
510
|
|
|
457
511
|
def test_bind_property_rejects_non_replaceable():
|
rune_runtime-2.2.1/netlify.toml
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
rune
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/base/math/RoundToNearest.py
RENAMED
|
File without changes
|
{rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/functions/specs/cdm/base/math/RoundingModeEnum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rune_runtime-2.2.1 → rune_runtime-2.2.2}/test/local_data/ird-ex01-vanilla-swap-versioned.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|