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.
Files changed (96) hide show
  1. famepy-0.1.0rc1/.gitignore +51 -0
  2. famepy-0.1.0rc1/.pre-commit-config.yaml +18 -0
  3. famepy-0.1.0rc1/CHANGELOG.md +59 -0
  4. famepy-0.1.0rc1/CONTRIBUTING.md +45 -0
  5. famepy-0.1.0rc1/LICENSE +21 -0
  6. famepy-0.1.0rc1/PKG-INFO +125 -0
  7. famepy-0.1.0rc1/README.md +101 -0
  8. famepy-0.1.0rc1/SECURITY.md +20 -0
  9. famepy-0.1.0rc1/docs/abi-checklist.md +110 -0
  10. famepy-0.1.0rc1/docs/benchmarks.md +196 -0
  11. famepy-0.1.0rc1/docs/capabilities.md +81 -0
  12. famepy-0.1.0rc1/docs/contracts.md +482 -0
  13. famepy-0.1.0rc1/docs/installation.md +102 -0
  14. famepy-0.1.0rc1/docs/migration.md +223 -0
  15. famepy-0.1.0rc1/docs/native-validation.md +454 -0
  16. famepy-0.1.0rc1/docs/parity.md +137 -0
  17. famepy-0.1.0rc1/docs/releasing.md +173 -0
  18. famepy-0.1.0rc1/docs/usage.md +208 -0
  19. famepy-0.1.0rc1/examples/retire_synthetic.py +92 -0
  20. famepy-0.1.0rc1/licenses/FAME.jl.txt +29 -0
  21. famepy-0.1.0rc1/pyproject.toml +60 -0
  22. famepy-0.1.0rc1/scripts/build_test_shim.py +43 -0
  23. famepy-0.1.0rc1/scripts/check_promotion.py +324 -0
  24. famepy-0.1.0rc1/scripts/check_public.py +55 -0
  25. famepy-0.1.0rc1/scripts/verify_artifacts.py +586 -0
  26. famepy-0.1.0rc1/src/famepy/__init__.py +130 -0
  27. famepy-0.1.0rc1/src/famepy/__main__.py +31 -0
  28. famepy-0.1.0rc1/src/famepy/_abi.py +141 -0
  29. famepy-0.1.0rc1/src/famepy/_binding.py +53 -0
  30. famepy-0.1.0rc1/src/famepy/_command.py +244 -0
  31. famepy-0.1.0rc1/src/famepy/_constants.py +258 -0
  32. famepy-0.1.0rc1/src/famepy/_data.py +604 -0
  33. famepy-0.1.0rc1/src/famepy/_database.py +182 -0
  34. famepy-0.1.0rc1/src/famepy/_discovery.py +96 -0
  35. famepy-0.1.0rc1/src/famepy/_errors.py +163 -0
  36. famepy-0.1.0rc1/src/famepy/_native.py +732 -0
  37. famepy-0.1.0rc1/src/famepy/_objects.py +146 -0
  38. famepy-0.1.0rc1/src/famepy/_probe.py +113 -0
  39. famepy-0.1.0rc1/src/famepy/_runtime.py +564 -0
  40. famepy-0.1.0rc1/src/famepy/_text.py +134 -0
  41. famepy-0.1.0rc1/src/famepy/_wildcard.py +276 -0
  42. famepy-0.1.0rc1/src/famepy/benchmarks/__init__.py +1313 -0
  43. famepy-0.1.0rc1/src/famepy/benchmarks/__main__.py +114 -0
  44. famepy-0.1.0rc1/src/famepy/benchmarks/_julia.py +546 -0
  45. famepy-0.1.0rc1/src/famepy/bridge/__init__.py +375 -0
  46. famepy-0.1.0rc1/src/famepy/bridge/_frequencies.py +343 -0
  47. famepy-0.1.0rc1/src/famepy/bridge/_values.py +672 -0
  48. famepy-0.1.0rc1/src/famepy/bridge/_workspace.py +707 -0
  49. famepy-0.1.0rc1/src/famepy/diagnostics.py +131 -0
  50. famepy-0.1.0rc1/src/famepy/migration/__init__.py +287 -0
  51. famepy-0.1.0rc1/src/famepy/migration/_layout.py +824 -0
  52. famepy-0.1.0rc1/src/famepy/migration/_migrate.py +808 -0
  53. famepy-0.1.0rc1/src/famepy/py.typed +0 -0
  54. famepy-0.1.0rc1/src/famepy/validation/__init__.py +501 -0
  55. famepy-0.1.0rc1/src/famepy/validation/__main__.py +101 -0
  56. famepy-0.1.0rc1/src/famepy/validation/_bridge_groups.py +1117 -0
  57. famepy-0.1.0rc1/src/famepy/validation/_child.py +153 -0
  58. famepy-0.1.0rc1/src/famepy/validation/_groups.py +1624 -0
  59. famepy-0.1.0rc1/src/famepy/validation/_julia.py +487 -0
  60. famepy-0.1.0rc1/src/famepy/validation/_manifest.py +86 -0
  61. famepy-0.1.0rc1/src/famepy/validation/_migration_group.py +571 -0
  62. famepy-0.1.0rc1/src/famepy/validation/_probe_dialogs.py +6 -0
  63. famepy-0.1.0rc1/src/famepy/validation/_process.py +237 -0
  64. famepy-0.1.0rc1/src/famepy/validation/_report.py +344 -0
  65. famepy-0.1.0rc1/src/famepy/validation/_schema.py +139 -0
  66. famepy-0.1.0rc1/src/famepy/validation/_text_group.py +759 -0
  67. famepy-0.1.0rc1/tests/conftest.py +41 -0
  68. famepy-0.1.0rc1/tests/fake_native.py +1296 -0
  69. famepy-0.1.0rc1/tests/native/shim.c +880 -0
  70. famepy-0.1.0rc1/tests/test_benchmarks.py +1111 -0
  71. famepy-0.1.0rc1/tests/test_bridge.py +204 -0
  72. famepy-0.1.0rc1/tests/test_bridge_frequencies.py +320 -0
  73. famepy-0.1.0rc1/tests/test_bridge_runner.py +269 -0
  74. famepy-0.1.0rc1/tests/test_bridge_values.py +579 -0
  75. famepy-0.1.0rc1/tests/test_bridge_workspace.py +570 -0
  76. famepy-0.1.0rc1/tests/test_command.py +258 -0
  77. famepy-0.1.0rc1/tests/test_compatibility.py +506 -0
  78. famepy-0.1.0rc1/tests/test_contracts.py +110 -0
  79. famepy-0.1.0rc1/tests/test_core_repair.py +820 -0
  80. famepy-0.1.0rc1/tests/test_data.py +291 -0
  81. famepy-0.1.0rc1/tests/test_database.py +236 -0
  82. famepy-0.1.0rc1/tests/test_foundation.py +218 -0
  83. famepy-0.1.0rc1/tests/test_lifecycle_isolation.py +242 -0
  84. famepy-0.1.0rc1/tests/test_migration.py +660 -0
  85. famepy-0.1.0rc1/tests/test_migration_runner.py +181 -0
  86. famepy-0.1.0rc1/tests/test_native_shim.py +486 -0
  87. famepy-0.1.0rc1/tests/test_probe_protocol.py +230 -0
  88. famepy-0.1.0rc1/tests/test_release_guards.py +657 -0
  89. famepy-0.1.0rc1/tests/test_review_edges.py +212 -0
  90. famepy-0.1.0rc1/tests/test_session.py +440 -0
  91. famepy-0.1.0rc1/tests/test_text_policy.py +345 -0
  92. famepy-0.1.0rc1/tests/test_text_runner.py +386 -0
  93. famepy-0.1.0rc1/tests/test_trusted_root.py +99 -0
  94. famepy-0.1.0rc1/tests/test_validation_runner.py +609 -0
  95. famepy-0.1.0rc1/tests/test_wildcard.py +120 -0
  96. 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.
@@ -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.
@@ -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.