FAMEPy 0.1.0rc1__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.
- famepy-0.1.0rc1/.gitignore +51 -0
- famepy-0.1.0rc1/.pre-commit-config.yaml +18 -0
- famepy-0.1.0rc1/CHANGELOG.md +59 -0
- famepy-0.1.0rc1/CONTRIBUTING.md +45 -0
- famepy-0.1.0rc1/LICENSE +21 -0
- famepy-0.1.0rc1/PKG-INFO +125 -0
- famepy-0.1.0rc1/README.md +101 -0
- famepy-0.1.0rc1/SECURITY.md +20 -0
- famepy-0.1.0rc1/docs/abi-checklist.md +110 -0
- famepy-0.1.0rc1/docs/benchmarks.md +196 -0
- famepy-0.1.0rc1/docs/capabilities.md +81 -0
- famepy-0.1.0rc1/docs/contracts.md +482 -0
- famepy-0.1.0rc1/docs/installation.md +102 -0
- famepy-0.1.0rc1/docs/migration.md +223 -0
- famepy-0.1.0rc1/docs/native-validation.md +454 -0
- famepy-0.1.0rc1/docs/parity.md +137 -0
- famepy-0.1.0rc1/docs/releasing.md +173 -0
- famepy-0.1.0rc1/docs/usage.md +208 -0
- famepy-0.1.0rc1/examples/retire_synthetic.py +92 -0
- famepy-0.1.0rc1/licenses/FAME.jl.txt +29 -0
- famepy-0.1.0rc1/pyproject.toml +60 -0
- famepy-0.1.0rc1/scripts/build_test_shim.py +43 -0
- famepy-0.1.0rc1/scripts/check_promotion.py +324 -0
- famepy-0.1.0rc1/scripts/check_public.py +55 -0
- famepy-0.1.0rc1/scripts/verify_artifacts.py +586 -0
- famepy-0.1.0rc1/src/famepy/__init__.py +130 -0
- famepy-0.1.0rc1/src/famepy/__main__.py +31 -0
- famepy-0.1.0rc1/src/famepy/_abi.py +141 -0
- famepy-0.1.0rc1/src/famepy/_binding.py +53 -0
- famepy-0.1.0rc1/src/famepy/_command.py +244 -0
- famepy-0.1.0rc1/src/famepy/_constants.py +258 -0
- famepy-0.1.0rc1/src/famepy/_data.py +604 -0
- famepy-0.1.0rc1/src/famepy/_database.py +182 -0
- famepy-0.1.0rc1/src/famepy/_discovery.py +96 -0
- famepy-0.1.0rc1/src/famepy/_errors.py +163 -0
- famepy-0.1.0rc1/src/famepy/_native.py +732 -0
- famepy-0.1.0rc1/src/famepy/_objects.py +146 -0
- famepy-0.1.0rc1/src/famepy/_probe.py +113 -0
- famepy-0.1.0rc1/src/famepy/_runtime.py +564 -0
- famepy-0.1.0rc1/src/famepy/_text.py +134 -0
- famepy-0.1.0rc1/src/famepy/_wildcard.py +276 -0
- famepy-0.1.0rc1/src/famepy/benchmarks/__init__.py +1313 -0
- famepy-0.1.0rc1/src/famepy/benchmarks/__main__.py +114 -0
- famepy-0.1.0rc1/src/famepy/benchmarks/_julia.py +546 -0
- famepy-0.1.0rc1/src/famepy/bridge/__init__.py +375 -0
- famepy-0.1.0rc1/src/famepy/bridge/_frequencies.py +343 -0
- famepy-0.1.0rc1/src/famepy/bridge/_values.py +672 -0
- famepy-0.1.0rc1/src/famepy/bridge/_workspace.py +707 -0
- famepy-0.1.0rc1/src/famepy/diagnostics.py +131 -0
- famepy-0.1.0rc1/src/famepy/migration/__init__.py +287 -0
- famepy-0.1.0rc1/src/famepy/migration/_layout.py +824 -0
- famepy-0.1.0rc1/src/famepy/migration/_migrate.py +808 -0
- famepy-0.1.0rc1/src/famepy/py.typed +0 -0
- famepy-0.1.0rc1/src/famepy/validation/__init__.py +501 -0
- famepy-0.1.0rc1/src/famepy/validation/__main__.py +101 -0
- famepy-0.1.0rc1/src/famepy/validation/_bridge_groups.py +1117 -0
- famepy-0.1.0rc1/src/famepy/validation/_child.py +153 -0
- famepy-0.1.0rc1/src/famepy/validation/_groups.py +1624 -0
- famepy-0.1.0rc1/src/famepy/validation/_julia.py +487 -0
- famepy-0.1.0rc1/src/famepy/validation/_manifest.py +86 -0
- famepy-0.1.0rc1/src/famepy/validation/_migration_group.py +571 -0
- famepy-0.1.0rc1/src/famepy/validation/_probe_dialogs.py +6 -0
- famepy-0.1.0rc1/src/famepy/validation/_process.py +237 -0
- famepy-0.1.0rc1/src/famepy/validation/_report.py +344 -0
- famepy-0.1.0rc1/src/famepy/validation/_schema.py +139 -0
- famepy-0.1.0rc1/src/famepy/validation/_text_group.py +759 -0
- famepy-0.1.0rc1/tests/conftest.py +41 -0
- famepy-0.1.0rc1/tests/fake_native.py +1296 -0
- famepy-0.1.0rc1/tests/native/shim.c +880 -0
- famepy-0.1.0rc1/tests/test_benchmarks.py +1111 -0
- famepy-0.1.0rc1/tests/test_bridge.py +204 -0
- famepy-0.1.0rc1/tests/test_bridge_frequencies.py +320 -0
- famepy-0.1.0rc1/tests/test_bridge_runner.py +269 -0
- famepy-0.1.0rc1/tests/test_bridge_values.py +579 -0
- famepy-0.1.0rc1/tests/test_bridge_workspace.py +570 -0
- famepy-0.1.0rc1/tests/test_command.py +258 -0
- famepy-0.1.0rc1/tests/test_compatibility.py +506 -0
- famepy-0.1.0rc1/tests/test_contracts.py +110 -0
- famepy-0.1.0rc1/tests/test_core_repair.py +820 -0
- famepy-0.1.0rc1/tests/test_data.py +291 -0
- famepy-0.1.0rc1/tests/test_database.py +236 -0
- famepy-0.1.0rc1/tests/test_foundation.py +218 -0
- famepy-0.1.0rc1/tests/test_lifecycle_isolation.py +242 -0
- famepy-0.1.0rc1/tests/test_migration.py +660 -0
- famepy-0.1.0rc1/tests/test_migration_runner.py +181 -0
- famepy-0.1.0rc1/tests/test_native_shim.py +486 -0
- famepy-0.1.0rc1/tests/test_probe_protocol.py +230 -0
- famepy-0.1.0rc1/tests/test_release_guards.py +657 -0
- famepy-0.1.0rc1/tests/test_review_edges.py +212 -0
- famepy-0.1.0rc1/tests/test_session.py +440 -0
- famepy-0.1.0rc1/tests/test_text_policy.py +345 -0
- famepy-0.1.0rc1/tests/test_text_runner.py +386 -0
- famepy-0.1.0rc1/tests/test_trusted_root.py +99 -0
- famepy-0.1.0rc1/tests/test_validation_runner.py +609 -0
- famepy-0.1.0rc1/tests/test_wildcard.py +120 -0
- famepy-0.1.0rc1/uv.lock +786 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Python environments, caches and build products
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
venv/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.coverage
|
|
10
|
+
.coverage.*
|
|
11
|
+
htmlcov/
|
|
12
|
+
coverage.xml
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
.tox/
|
|
17
|
+
.nox/
|
|
18
|
+
.cache/
|
|
19
|
+
|
|
20
|
+
# Compiled artifacts and local FAME installations
|
|
21
|
+
*.dll
|
|
22
|
+
*.so
|
|
23
|
+
*.so.*
|
|
24
|
+
*.dylib
|
|
25
|
+
*.pyd
|
|
26
|
+
*.o
|
|
27
|
+
*.obj
|
|
28
|
+
*.lib
|
|
29
|
+
*.a
|
|
30
|
+
vendor/
|
|
31
|
+
|
|
32
|
+
# Local databases, diagnostics and reports; synthetic fixtures can be added
|
|
33
|
+
# explicitly after review. Never add production databases to this repository.
|
|
34
|
+
*.db
|
|
35
|
+
*.db.*
|
|
36
|
+
*.sqlite
|
|
37
|
+
*.sqlite3
|
|
38
|
+
test-results/
|
|
39
|
+
local-results/
|
|
40
|
+
*.log
|
|
41
|
+
|
|
42
|
+
# Credentials and local editor settings
|
|
43
|
+
.env
|
|
44
|
+
.env.*
|
|
45
|
+
!.env.example
|
|
46
|
+
.vscode/
|
|
47
|
+
.idea/
|
|
48
|
+
.DS_Store
|
|
49
|
+
Thumbs.db
|
|
50
|
+
*.swp
|
|
51
|
+
*~
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: local
|
|
3
|
+
hooks:
|
|
4
|
+
- id: public-files
|
|
5
|
+
name: public text hygiene and privacy patterns
|
|
6
|
+
entry: python scripts/check_public.py
|
|
7
|
+
language: system
|
|
8
|
+
types: [text]
|
|
9
|
+
- id: ruff
|
|
10
|
+
name: ruff
|
|
11
|
+
entry: python -m ruff check
|
|
12
|
+
language: system
|
|
13
|
+
types: [python]
|
|
14
|
+
- id: ruff-format
|
|
15
|
+
name: ruff format
|
|
16
|
+
entry: python -m ruff format --check
|
|
17
|
+
language: system
|
|
18
|
+
types_or: [python, markdown]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions follow [PEP 440](https://peps.python.org/pep-0440/). A version
|
|
4
|
+
is built and verified once by a rehearsal run whose artifact is reviewed,
|
|
5
|
+
and only that reviewed artifact is promoted to the index (see
|
|
6
|
+
[releasing](docs/releasing.md)). An entry marked *unreleased* has not been
|
|
7
|
+
promoted.
|
|
8
|
+
|
|
9
|
+
## 0.1.0rc1 (unreleased)
|
|
10
|
+
|
|
11
|
+
First release candidate. FAMEPy is a pure-Python package that binds the
|
|
12
|
+
FAME CHLI library through `ctypes`, with the behavior of
|
|
13
|
+
[FAME.jl](https://github.com/bankofcanada/FAME.jl) as the reference and
|
|
14
|
+
[TimeSeriesEconPy](https://github.com/Nic2020/TimeSeriesEconPy) as the
|
|
15
|
+
time-series model. A separately installed, licensed FAME runtime is
|
|
16
|
+
required for every native operation; nothing of it is distributed.
|
|
17
|
+
|
|
18
|
+
Included:
|
|
19
|
+
|
|
20
|
+
- Runtime lifecycle: one initialization per process, terminal
|
|
21
|
+
finalization, trusted library discovery through `FAME` or
|
|
22
|
+
`FAMEPY_LIBRARY`, diagnostics and a subprocess symbol probe without
|
|
23
|
+
native calls.
|
|
24
|
+
- Databases: the five local access modes, the work database, explicit
|
|
25
|
+
posting, connection strings passed through the local open (the
|
|
26
|
+
reference's read-only remote route); the server-connection write modes
|
|
27
|
+
are refused before any native call, as neither wrapper binds them.
|
|
28
|
+
- Raw object I/O for precision, numeric, Boolean, date, string and
|
|
29
|
+
namelist scalars and series with preserved missing categories,
|
|
30
|
+
subranges, exact-width scalars and complete validation before the first
|
|
31
|
+
native call; wildcard listing with filters; command execution with
|
|
32
|
+
recursive `INPUT` expansion; opt-in extended error text.
|
|
33
|
+
- The TimeSeriesEconPy bridge: every reference value kind, every reference
|
|
34
|
+
frequency anchor, workspace, mapping and multivariate writes, workspace
|
|
35
|
+
reads with name transformation, per-object reporting variants, and the
|
|
36
|
+
missing, empty and text policies. String values are ASCII by default and
|
|
37
|
+
can be exchanged as raw bytes or, opt-in, as strict UTF-8; names, paths
|
|
38
|
+
and commands stay ASCII.
|
|
39
|
+
- A FAME-to-DataEcon migration workflow with a plan-first, refuse-by-default
|
|
40
|
+
loss policy and structural verification on read.
|
|
41
|
+
- A consolidated native validation runner (eleven groups, isolated worker
|
|
42
|
+
processes, sanitized reports, optional FAME.jl differential checks) and a
|
|
43
|
+
benchmark harness with verified read-backs.
|
|
44
|
+
|
|
45
|
+
Evidence for this candidate is summarized in
|
|
46
|
+
[capability status](docs/capabilities.md) and the
|
|
47
|
+
[parity ledger](docs/parity.md): the eleven validation groups passed on one
|
|
48
|
+
Windows and one Linux installation with the FAME.jl comparisons configured
|
|
49
|
+
on both, the benchmark scenarios completed on both, and a bounded read-only
|
|
50
|
+
comparison of one small approved remote selection was equal through both
|
|
51
|
+
wrappers on both hosts. These are statements about the inspected
|
|
52
|
+
installations, not blanket version coverage.
|
|
53
|
+
|
|
54
|
+
Deliberate differences from the reference are documented in
|
|
55
|
+
[contracts](docs/contracts.md) and the ledger: no restart of the runtime in
|
|
56
|
+
one process, missing Booleans refused instead of read as `true`, a scalar
|
|
57
|
+
NaN written as NC, integer scalars kept exact or refused, an explicit mode
|
|
58
|
+
required for path writes, and whole-value UTF-8 decoding instead of the
|
|
59
|
+
reference's byte-length slicing.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Treat every tracked file, commit, workflow log, issue and distribution as public.
|
|
4
|
+
Keep internal project labels, private plans and links, personal contact details,
|
|
5
|
+
staff names and institutional discussions out of these surfaces. Retain legally
|
|
6
|
+
required copyright notices and factual upstream attribution. Use the project
|
|
7
|
+
contact `statespaceecon@gmail.com` where a contact address is needed.
|
|
8
|
+
|
|
9
|
+
Use synthetic test data. Do not add production databases, connection strings,
|
|
10
|
+
credentials, vendor headers, help files, licensed libraries or raw diagnostic
|
|
11
|
+
logs. Review generated files as carefully as source. Ignore rules and automated
|
|
12
|
+
checks assist review; they cannot prove that an arbitrary file is safe to publish.
|
|
13
|
+
|
|
14
|
+
## Development
|
|
15
|
+
|
|
16
|
+
Python 3.11 or newer is required. The foundation is tested without FAME:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
uv sync --locked
|
|
20
|
+
uv run ruff check .
|
|
21
|
+
uv run ruff format --check .
|
|
22
|
+
uv run mypy
|
|
23
|
+
uv run pytest
|
|
24
|
+
uv run pre-commit run --all-files
|
|
25
|
+
uv build
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Unit tests use the in-memory fake backend in `tests/fake_native.py`; it models
|
|
29
|
+
the package's own contracts and is not FAME behavior evidence. The validation
|
|
30
|
+
runner's self-test drives that fake through real subprocesses.
|
|
31
|
+
|
|
32
|
+
The independent C shim needs a compiler (MSVC on Windows, GCC/Clang on Linux).
|
|
33
|
+
Run from a compiler-enabled terminal:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
uv run python scripts/build_test_shim.py
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Set `FAMEPY_TEST_SHIM` to the **absolute** path printed by the builder, then run
|
|
40
|
+
pytest again. CI requires these tests; an ordinary developer run without the
|
|
41
|
+
variable reports them as skipped. The shim contains no vendor code and does not
|
|
42
|
+
certify FAME compatibility. See [native validation](docs/native-validation.md).
|
|
43
|
+
|
|
44
|
+
Install hooks with `uv run pre-commit install` if desired. Before publication,
|
|
45
|
+
review Git history and built wheel/sdist contents as well as the current tree.
|
famepy-0.1.0rc1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nic2020
|
|
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.
|
famepy-0.1.0rc1/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: FAMEPy
|
|
3
|
+
Version: 0.1.0rc1
|
|
4
|
+
Summary: Python bindings and time-series integration for the FAME CHLI library
|
|
5
|
+
Project-URL: Repository, https://github.com/Nic2020/FAMEPy
|
|
6
|
+
Project-URL: Issues, https://github.com/Nic2020/FAMEPy/issues
|
|
7
|
+
License-Expression: MIT AND BSD-3-Clause
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
License-File: licenses/FAME.jl.txt
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: numpy>=1.26
|
|
22
|
+
Requires-Dist: timeserieseconpy>=0.0.1.dev3
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# FAMEPy
|
|
26
|
+
|
|
27
|
+
Python bindings for the FAME CHLI library with integration for
|
|
28
|
+
[TimeSeriesEconPy](https://github.com/Nic2020/TimeSeriesEconPy).
|
|
29
|
+
The behavioral reference is
|
|
30
|
+
[FAME.jl](https://github.com/bankofcanada/FAME.jl).
|
|
31
|
+
|
|
32
|
+
**Status: first release candidate (0.1.0rc1). The operational core,
|
|
33
|
+
the full TimeSeriesEconPy bridge (runtime lifecycle, local databases, raw
|
|
34
|
+
object I/O, listing, commands, every reference frequency anchor, every
|
|
35
|
+
value kind, workspace reads and writes, the string value text policies),
|
|
36
|
+
the opt-in extended error text and the FAME-to-DataEcon migration
|
|
37
|
+
workflow passed the consolidated eleven-group validation campaign on one
|
|
38
|
+
Windows and one Linux host with an installed FAME, with the FAME.jl
|
|
39
|
+
comparisons configured on both; the benchmark harness completed its
|
|
40
|
+
scenarios on both; and a bounded read-only comparison of one small
|
|
41
|
+
approved remote selection was equal through the reference and this
|
|
42
|
+
package on both hosts. See [capability status](docs/capabilities.md),
|
|
43
|
+
the [parity ledger](docs/parity.md) and the [changelog](CHANGELOG.md).
|
|
44
|
+
These are statements about the inspected installations, not blanket
|
|
45
|
+
version coverage.**
|
|
46
|
+
|
|
47
|
+
Implemented: runtime lifecycle, databases (the five local access modes, work
|
|
48
|
+
database, explicit posting), raw scalar and series I/O for precision,
|
|
49
|
+
numeric, Boolean, date, string and namelist objects with preserved missing
|
|
50
|
+
categories, wildcard listing with filters, command execution with recursive
|
|
51
|
+
INPUT expansion, and the TimeSeriesEconPy bridge: values of every reference
|
|
52
|
+
kind, all reference frequency anchors, workspace/mapping/multivariate
|
|
53
|
+
writes and workspace reads with name transformation and per-object
|
|
54
|
+
reporting, with string values as ASCII, raw bytes or strict UTF-8.
|
|
55
|
+
Also: opt-in extended error text, a
|
|
56
|
+
[FAME-to-DataEcon migration workflow](docs/migration.md) and a
|
|
57
|
+
[benchmark harness](docs/benchmarks.md).
|
|
58
|
+
Not implemented: server-connection writes (the reference's remote route is
|
|
59
|
+
read-only and neither wrapper binds a named-connection write API),
|
|
60
|
+
multivariate reconstruction on read (not in the reference either).
|
|
61
|
+
|
|
62
|
+
Windows and Linux x86-64 are the intended runtime platforms. A separately
|
|
63
|
+
installed, licensed FAME runtime is required for FAME operations; it is not
|
|
64
|
+
distributed with this project. FAMEPy depends on TimeSeriesEconPy;
|
|
65
|
+
TimeSeriesEconPy remains independent of FAMEPy and FAME.
|
|
66
|
+
|
|
67
|
+
## Install and try
|
|
68
|
+
|
|
69
|
+
From a clone, with Python 3.11 or newer:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
python -m pip install .
|
|
73
|
+
python -m famepy # discovery report, exits 1 without FAME
|
|
74
|
+
python -m famepy --probe # symbol presence in a subprocess, no CHLI calls
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The package builds without FAME, vendor headers or a C compiler and does not
|
|
78
|
+
bundle FAME. Set `FAME` to the installation (required for licensing) or
|
|
79
|
+
`FAMEPY_LIBRARY` to an absolute trusted library path. Load only trusted
|
|
80
|
+
native libraries.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import famepy
|
|
84
|
+
from famepy import bridge
|
|
85
|
+
from tsecon import TSeries, mm
|
|
86
|
+
|
|
87
|
+
famepy.initialize() # once per process
|
|
88
|
+
bridge.write_tseries("synthetic.db", "ts", TSeries(mm(2020, 1), [1.0, 2.0]), mode="create")
|
|
89
|
+
print(bridge.read_tseries("synthetic.db", "ts"))
|
|
90
|
+
famepy.finalize() # terminal; use a new process for another runtime
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
See [installation](docs/installation.md) (including offline wheelhouses),
|
|
94
|
+
[usage](docs/usage.md), [contracts](docs/contracts.md),
|
|
95
|
+
[capability status](docs/capabilities.md), the [parity ledger](docs/parity.md),
|
|
96
|
+
[migration](docs/migration.md), [benchmarks](docs/benchmarks.md),
|
|
97
|
+
[native validation](docs/native-validation.md),
|
|
98
|
+
the [ABI checklist](docs/abi-checklist.md), [releasing](docs/releasing.md),
|
|
99
|
+
the [changelog](CHANGELOG.md), [contributing](CONTRIBUTING.md)
|
|
100
|
+
and [security/privacy](SECURITY.md).
|
|
101
|
+
|
|
102
|
+
## Validating against an installed FAME
|
|
103
|
+
|
|
104
|
+
`python -m famepy.validation --native --scratch <new-dir> --report <file>` runs
|
|
105
|
+
the consolidated campaign (lifecycle, databases, raw types, discovery,
|
|
106
|
+
commands, bridge, frequencies, workspace, extended errors, migration, text) in
|
|
107
|
+
isolated subprocesses inside a fresh run directory of a new or empty
|
|
108
|
+
scratch, and writes one schema-validated report without paths or native
|
|
109
|
+
text. A group passes only when every required case passed.
|
|
110
|
+
`python -m famepy.benchmarks --native ...` produces the separate benchmark
|
|
111
|
+
report. See [native validation](docs/native-validation.md).
|
|
112
|
+
|
|
113
|
+
## Repository conventions
|
|
114
|
+
|
|
115
|
+
Text files use UTF-8 and LF on Windows and Linux, except Windows batch scripts.
|
|
116
|
+
Git attributes preserve database and native-library files as binary.
|
|
117
|
+
Local databases, FAME binaries, environments and test reports are ignored.
|
|
118
|
+
Do not commit licensed runtime files or private database contents.
|
|
119
|
+
|
|
120
|
+
## Licensing
|
|
121
|
+
|
|
122
|
+
Original code uses the MIT license in `LICENSE`. Code tables, ABI declarations
|
|
123
|
+
and behavior adapted from FAME.jl retain its BSD 3-Clause notices in
|
|
124
|
+
[licenses/FAME.jl.txt](licenses/FAME.jl.txt). Both licenses ship with the package.
|
|
125
|
+
FAME itself is a separate proprietary product.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# FAMEPy
|
|
2
|
+
|
|
3
|
+
Python bindings for the FAME CHLI library with integration for
|
|
4
|
+
[TimeSeriesEconPy](https://github.com/Nic2020/TimeSeriesEconPy).
|
|
5
|
+
The behavioral reference is
|
|
6
|
+
[FAME.jl](https://github.com/bankofcanada/FAME.jl).
|
|
7
|
+
|
|
8
|
+
**Status: first release candidate (0.1.0rc1). The operational core,
|
|
9
|
+
the full TimeSeriesEconPy bridge (runtime lifecycle, local databases, raw
|
|
10
|
+
object I/O, listing, commands, every reference frequency anchor, every
|
|
11
|
+
value kind, workspace reads and writes, the string value text policies),
|
|
12
|
+
the opt-in extended error text and the FAME-to-DataEcon migration
|
|
13
|
+
workflow passed the consolidated eleven-group validation campaign on one
|
|
14
|
+
Windows and one Linux host with an installed FAME, with the FAME.jl
|
|
15
|
+
comparisons configured on both; the benchmark harness completed its
|
|
16
|
+
scenarios on both; and a bounded read-only comparison of one small
|
|
17
|
+
approved remote selection was equal through the reference and this
|
|
18
|
+
package on both hosts. See [capability status](docs/capabilities.md),
|
|
19
|
+
the [parity ledger](docs/parity.md) and the [changelog](CHANGELOG.md).
|
|
20
|
+
These are statements about the inspected installations, not blanket
|
|
21
|
+
version coverage.**
|
|
22
|
+
|
|
23
|
+
Implemented: runtime lifecycle, databases (the five local access modes, work
|
|
24
|
+
database, explicit posting), raw scalar and series I/O for precision,
|
|
25
|
+
numeric, Boolean, date, string and namelist objects with preserved missing
|
|
26
|
+
categories, wildcard listing with filters, command execution with recursive
|
|
27
|
+
INPUT expansion, and the TimeSeriesEconPy bridge: values of every reference
|
|
28
|
+
kind, all reference frequency anchors, workspace/mapping/multivariate
|
|
29
|
+
writes and workspace reads with name transformation and per-object
|
|
30
|
+
reporting, with string values as ASCII, raw bytes or strict UTF-8.
|
|
31
|
+
Also: opt-in extended error text, a
|
|
32
|
+
[FAME-to-DataEcon migration workflow](docs/migration.md) and a
|
|
33
|
+
[benchmark harness](docs/benchmarks.md).
|
|
34
|
+
Not implemented: server-connection writes (the reference's remote route is
|
|
35
|
+
read-only and neither wrapper binds a named-connection write API),
|
|
36
|
+
multivariate reconstruction on read (not in the reference either).
|
|
37
|
+
|
|
38
|
+
Windows and Linux x86-64 are the intended runtime platforms. A separately
|
|
39
|
+
installed, licensed FAME runtime is required for FAME operations; it is not
|
|
40
|
+
distributed with this project. FAMEPy depends on TimeSeriesEconPy;
|
|
41
|
+
TimeSeriesEconPy remains independent of FAMEPy and FAME.
|
|
42
|
+
|
|
43
|
+
## Install and try
|
|
44
|
+
|
|
45
|
+
From a clone, with Python 3.11 or newer:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
python -m pip install .
|
|
49
|
+
python -m famepy # discovery report, exits 1 without FAME
|
|
50
|
+
python -m famepy --probe # symbol presence in a subprocess, no CHLI calls
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The package builds without FAME, vendor headers or a C compiler and does not
|
|
54
|
+
bundle FAME. Set `FAME` to the installation (required for licensing) or
|
|
55
|
+
`FAMEPY_LIBRARY` to an absolute trusted library path. Load only trusted
|
|
56
|
+
native libraries.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import famepy
|
|
60
|
+
from famepy import bridge
|
|
61
|
+
from tsecon import TSeries, mm
|
|
62
|
+
|
|
63
|
+
famepy.initialize() # once per process
|
|
64
|
+
bridge.write_tseries("synthetic.db", "ts", TSeries(mm(2020, 1), [1.0, 2.0]), mode="create")
|
|
65
|
+
print(bridge.read_tseries("synthetic.db", "ts"))
|
|
66
|
+
famepy.finalize() # terminal; use a new process for another runtime
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
See [installation](docs/installation.md) (including offline wheelhouses),
|
|
70
|
+
[usage](docs/usage.md), [contracts](docs/contracts.md),
|
|
71
|
+
[capability status](docs/capabilities.md), the [parity ledger](docs/parity.md),
|
|
72
|
+
[migration](docs/migration.md), [benchmarks](docs/benchmarks.md),
|
|
73
|
+
[native validation](docs/native-validation.md),
|
|
74
|
+
the [ABI checklist](docs/abi-checklist.md), [releasing](docs/releasing.md),
|
|
75
|
+
the [changelog](CHANGELOG.md), [contributing](CONTRIBUTING.md)
|
|
76
|
+
and [security/privacy](SECURITY.md).
|
|
77
|
+
|
|
78
|
+
## Validating against an installed FAME
|
|
79
|
+
|
|
80
|
+
`python -m famepy.validation --native --scratch <new-dir> --report <file>` runs
|
|
81
|
+
the consolidated campaign (lifecycle, databases, raw types, discovery,
|
|
82
|
+
commands, bridge, frequencies, workspace, extended errors, migration, text) in
|
|
83
|
+
isolated subprocesses inside a fresh run directory of a new or empty
|
|
84
|
+
scratch, and writes one schema-validated report without paths or native
|
|
85
|
+
text. A group passes only when every required case passed.
|
|
86
|
+
`python -m famepy.benchmarks --native ...` produces the separate benchmark
|
|
87
|
+
report. See [native validation](docs/native-validation.md).
|
|
88
|
+
|
|
89
|
+
## Repository conventions
|
|
90
|
+
|
|
91
|
+
Text files use UTF-8 and LF on Windows and Linux, except Windows batch scripts.
|
|
92
|
+
Git attributes preserve database and native-library files as binary.
|
|
93
|
+
Local databases, FAME binaries, environments and test reports are ignored.
|
|
94
|
+
Do not commit licensed runtime files or private database contents.
|
|
95
|
+
|
|
96
|
+
## Licensing
|
|
97
|
+
|
|
98
|
+
Original code uses the MIT license in `LICENSE`. Code tables, ABI declarations
|
|
99
|
+
and behavior adapted from FAME.jl retain its BSD 3-Clause notices in
|
|
100
|
+
[licenses/FAME.jl.txt](licenses/FAME.jl.txt). Both licenses ship with the package.
|
|
101
|
+
FAME itself is a separate proprietary product.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Security and privacy
|
|
2
|
+
|
|
3
|
+
Report security issues privately to `statespaceecon@gmail.com`. Please provide
|
|
4
|
+
a synthetic reproduction and omit credentials, private databases and raw logs.
|
|
5
|
+
This project is in its first release-candidate cycle; no production support
|
|
6
|
+
or response-time guarantee is currently offered.
|
|
7
|
+
|
|
8
|
+
Importing FAMEPy does not load FAME. Library discovery uses explicit absolute
|
|
9
|
+
paths or the configured FAME installation, not a current-directory/PATH search.
|
|
10
|
+
Only point the optional probe at trusted libraries: loading a native library
|
|
11
|
+
executes its loader code. A subprocess limits the effect of a crash; it is not
|
|
12
|
+
a security sandbox.
|
|
13
|
+
|
|
14
|
+
Diagnostic reports intentionally omit paths, hostnames and raw loader output.
|
|
15
|
+
Review reports before sharing them. FAMEPy does not transmit reports or perform
|
|
16
|
+
network requests of its own. Opening a database through a connection string
|
|
17
|
+
is an explicit user operation on the caller's already configured route; the
|
|
18
|
+
string is passed to the library unchanged and never appears in diagnostics,
|
|
19
|
+
`repr` or error messages. No vendor runtime, credentials or databases are
|
|
20
|
+
bundled.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Per-function ABI checklist
|
|
2
|
+
|
|
3
|
+
This table lists every native call the package and its validation runner use,
|
|
4
|
+
with the candidate declaration the package binds. Before the first native
|
|
5
|
+
campaign on a host, compare each row with the installed header and record
|
|
6
|
+
match or difference per row (conclusions only, never header text). A mismatch
|
|
7
|
+
blocks the operations that use that row, not unrelated groups.
|
|
8
|
+
|
|
9
|
+
Conventions: `cfm*` functions return `void` and take a leading `int *status`
|
|
10
|
+
(the binding initializes it to -1 and treats any nonzero result as failure);
|
|
11
|
+
`fame_*` functions return `int` status. `int` is 32-bit signed, `index` is the
|
|
12
|
+
64-bit signed `fame_index`, `range` is the 24-byte structure `{int frequency;
|
|
13
|
+
index start; index end}` with offsets 0/8/16 and alignment 8. Text is passed
|
|
14
|
+
as NUL-terminated `char *`; the package sends NUL-free bytes and accepts only
|
|
15
|
+
ASCII `str` values in this release. "Owned" means the package allocates the
|
|
16
|
+
buffer and keeps it alive for the call. Every text argument carries its
|
|
17
|
+
direction: `in/out text` is text the older calling convention lets the
|
|
18
|
+
library rewrite in place (trimmed, upper-cased), so the binding passes an
|
|
19
|
+
owned NUL-terminated copy (`char *`), never the caller's bytes; `input text`
|
|
20
|
+
is documented as input only (`const char *` in the newer convention) and is
|
|
21
|
+
passed as given. Pointer widths are the same either way; the distinction
|
|
22
|
+
is ownership, and it must be confirmed against the installed header per
|
|
23
|
+
host like every other row rather than inferred from a passing width check.
|
|
24
|
+
|
|
25
|
+
| Function | Candidate arguments (after status where applicable) | Direction and ownership | Used by |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| cfmini | none | initializes the library; requires the FAME environment variable for licensing | lifecycle |
|
|
28
|
+
| cfmfin | none | finalizes; all handles become invalid | lifecycle |
|
|
29
|
+
| cfmver | `float *version` | output, owned 4-byte float | lifecycle |
|
|
30
|
+
| cfmfame | `char *command` | input text, NUL-terminated, at most 2**20 bytes (reference-derived bound) | commands |
|
|
31
|
+
| cfmopwk | `int *key` | output database key | database |
|
|
32
|
+
| cfmopdb | `int *key, char *name, int mode` | output key; in/out text (owned copy; the library trims it); mode 1-5 for this local open (6 and 7 are modes of the open on a named server connection, which is not bound, and are refused before the call; the local open is documented to return the bad-mode status for them) | database |
|
|
33
|
+
| cfmpodb | `int key` | posts updates | database |
|
|
34
|
+
| cfmcldb | `int key` | closes without posting | database |
|
|
35
|
+
| cfmsopt | `char *option, char *value` | in/out texts (owned copies; the library trims and upper-cases both), for example `ITEM CLASS` / `ON`; frequency selections use the documented family words (`ITEM FREQUENCY MONTHLY`, ...) and index selections `ITEM INDEX CASE` / `DATE` | discovery |
|
|
36
|
+
| cfmnlen | `int key, char *name, int item(-1), int *length` | in/out name (owned copy); output length excluding terminator | raw data |
|
|
37
|
+
| cfmgtnl | `int key, char *name, int item(-1), char *buffer, int capacity, int *length` | in/out name (owned copy); owned writable buffer of capacity+1 bytes; the whole list comes back as members within braces separated by commas, in the library's own layout | raw data |
|
|
38
|
+
| cfmwtnl | `int key, char *name, int item(-1), char *text` | in/out name and in/out list text (owned copies; the library trims and upper-cases them) | raw data |
|
|
39
|
+
| cfmdlob | `int key, char *name` | in/out name (owned copy); deletes; status 13 when absent | raw data |
|
|
40
|
+
| cfmnwob | `int key, char *name, int class, int frequency, int type, int basis, int observed` | in/out name (owned copy); creates an empty object | raw data |
|
|
41
|
+
| cfmispm | `double value, int *type` | classification output 0-4 | raw data |
|
|
42
|
+
| cfmisnm | `float value, int *type` | classification output | raw data |
|
|
43
|
+
| cfmisbm | `int value, int *type` | classification output | raw data |
|
|
44
|
+
| cfmissm | `char *value, int *type` | input text; classification output | raw data |
|
|
45
|
+
| fame_index_to_year_period | `int frequency, index value, int *year, int *period` | outputs owned | bridge |
|
|
46
|
+
| fame_year_period_to_index | `int frequency, index *out, int year, int period` | 64-bit output (the reference declares this inconsistently; the 64-bit form is used) | bridge |
|
|
47
|
+
| fame_quick_info | `int key, const char *name, int *class, int *type, int *frequency, index *first, index *last` | outputs owned | all |
|
|
48
|
+
| fame_init_wildcard | `int key, int *cursor, const char *pattern, int 0, const char *NULL` | output cursor key | discovery |
|
|
49
|
+
| fame_get_next_wildcard | `int cursor, char *name, int *class, int *type, int *frequency, index *first, index *last, int capacity, int *length` | owned name buffer of capacity+1 bytes; 242-byte capacity; status 18 when longer, with the full length in `length` | discovery |
|
|
50
|
+
| fame_free_wildcard | `int cursor` | releases the cursor; always called in `finally` | discovery |
|
|
51
|
+
| fame_get_precisions | `int key, const char *name, range *range_or_NULL, double *values` | owned float64 buffer of range length (1 for scalars) | raw data |
|
|
52
|
+
| fame_get_numerics | same with `float *values` | owned float32 buffer | raw data |
|
|
53
|
+
| fame_get_booleans | same with `int *values` | owned int32 buffer | raw data |
|
|
54
|
+
| fame_get_dates | same with `index *values` | owned int64 buffer | raw data |
|
|
55
|
+
| fame_len_strings | `int key, const char *name, range *, int *lengths` | owned int32 buffer of range length | raw data |
|
|
56
|
+
| fame_get_strings | `int key, const char *name, range *, char **values, const int *inlen, int *outlen(NULL)` | owned array of owned buffers sized from `fame_len_strings` plus terminators; `inlen` carries those capacities; the optional `outlen` output lengths are not requested (NULL) | raw data |
|
|
57
|
+
| fame_write_precisions | `int key, const char *name, range *, const double *values` | caller's validated float64 buffer, never converted | raw data |
|
|
58
|
+
| fame_write_numerics | same with `const float *` | caller's float32 buffer | raw data |
|
|
59
|
+
| fame_write_booleans | same with `const int *` | caller's int32 buffer | raw data |
|
|
60
|
+
| fame_write_dates | `int key, const char *name, range *, int type, const index *values` | caller's int64 buffer; `type` is the frequency code of the dates | raw data |
|
|
61
|
+
| fame_write_strings | `int key, const char *name, range *, char **values` | owned array of pointers to NUL-terminated byte strings | raw data |
|
|
62
|
+
| fame_date_missing_type | `index value, int *type` | classification output | raw data |
|
|
63
|
+
| cfmlerr | `int *length` (older convention: leading status pointer, void return) | output length of the pending extended error text, excluding the terminator; called only by the opt-in retrieval, immediately before `cfmferr` with a buffer of that length plus one | extended errors |
|
|
64
|
+
|
|
65
|
+
## Native globals
|
|
66
|
+
|
|
67
|
+
| Symbol | Candidate type | Use |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| FAME_INDEX_NC, FAME_INDEX_NA, FAME_INDEX_ND | signed 64-bit | date/index missing sentinels; NC marks empty series ranges |
|
|
70
|
+
| FPRCNC, FPRCNA, FPRCND | double | precision sentinels |
|
|
71
|
+
| FNUMNC, FNUMNA, FNUMND | float | numeric sentinels |
|
|
72
|
+
| FBOONC, FBOONA, FBOOND | int | Boolean sentinels |
|
|
73
|
+
| FSTRNC, FSTRNA, FSTRND | `char[3]` arrays (reported on both inspected installations) | string sentinels; read as bounded arrays, never as pointers |
|
|
74
|
+
|
|
75
|
+
The package reads the globals once after initialization and compares data
|
|
76
|
+
against them by bit pattern. The validation campaign checks that classifier
|
|
77
|
+
against the library's own `cfmis*m`/`fame_date_missing_type` results before
|
|
78
|
+
the bitwise form is relied on.
|
|
79
|
+
|
|
80
|
+
## Constants
|
|
81
|
+
|
|
82
|
+
| Constant | Value used | Source |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| HSUCC | 0 | reference |
|
|
85
|
+
| HBMODE | 5 | vendor status help (bad or unauthorized access mode, or database not open for the requested access); returned by the local open for modes 6 and 7 on both inspected installations |
|
|
86
|
+
| HNOOBJ | 13 | reference; header-confirmed |
|
|
87
|
+
| HTRUNC | 18 | header-confirmed on both inspected installations |
|
|
88
|
+
| HBOPT | 67 | reference; header-confirmed |
|
|
89
|
+
| HFMENV / HLICFL | 97 / 98 | vendor status help (licensing environment / license file) |
|
|
90
|
+
| HFAMER | 513 | header-confirmed; extended text needs the opt-in path |
|
|
91
|
+
| HNAMLEN | 242 (buffer 243) | header-confirmed v4 name capacity |
|
|
92
|
+
| HNLALL | -1 | reference namelist selector |
|
|
93
|
+
| class, type, frequency, basis, observed codes | as in `famepy._constants` | reference tables |
|
|
94
|
+
|
|
95
|
+
Unknowns to record per host: the text encoding the library expects for
|
|
96
|
+
names, paths and commands, and whether initialization has root-level
|
|
97
|
+
dependency requirements beyond the library directory. The `cfmlerr` row was
|
|
98
|
+
recorded as the older convention on both inspected installations and is now
|
|
99
|
+
bound; its first native call happens in the `extended_errors` group. Both hosts
|
|
100
|
+
confirmed that initialization happens once per process and that
|
|
101
|
+
finalization is the last native call. Per host, the campaign records rather
|
|
102
|
+
than assumes: the rule for missing observations at the ends of a written
|
|
103
|
+
range per value type (both inspected installations dropped leading and
|
|
104
|
+
trailing ND, emptied all-ND ranges and kept NC and NA endpoints); the
|
|
105
|
+
layout the library uses for a whole namelist (nine bytes for a three-member
|
|
106
|
+
list on both); and the counts the documented family and index words select
|
|
107
|
+
on their own. Whether a given installation's header matches these
|
|
108
|
+
candidate directions, and whether its release honors the documented family
|
|
109
|
+
and index words, is confirmed per host by the checklist review and the
|
|
110
|
+
campaign, never assumed from documentation.
|