nativegate 0.1.0__tar.gz → 0.1.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.
- {nativegate-0.1.0 → nativegate-0.1.2}/PKG-INFO +8 -1
- {nativegate-0.1.0 → nativegate-0.1.2}/README.md +7 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/cli.py +27 -2
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/pyproject_gen.py +14 -2
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/PKG-INFO +8 -1
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/SOURCES.txt +2 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/pyproject.toml +1 -1
- nativegate-0.1.2/tests/test_pyproject_gen.py +24 -0
- nativegate-0.1.2/tests/test_service_name_validation.py +47 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/__init__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/__main__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/buildinfo.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/config.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/declared_invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/discovery.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/driverbuild.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/drivers/__init__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/drivers/cpp.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/drivers/fortran.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/__init__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/cmake_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/docker_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/error_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/f2py_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/gateway_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/golden_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/k8s_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/mcp_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/middleware_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/pybind_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/python_pkg_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/generators/test_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/golden.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/ir.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/lattice.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/locking.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/oracle.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/__init__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/cpp.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/cpp_ast.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/cpp_regex.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/fixed_form.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/fortran.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/fortran_fparser.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/parsers/fortran_regex.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/preprocess.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/structural_invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/suggest.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/templates/__init__.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/templates/golden_test_template.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate/wire.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/dependency_links.txt +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/entry_points.txt +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/requires.txt +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/nativegate.egg-info/top_level.txt +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/setup.cfg +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_buildinfo.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cli_serve_verify.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cli_suggest.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cli_verify_aggregate.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cmake_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cpp_ast.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cpp_driver.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_cpp_pipeline.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_declared_invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_derived_types.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_docker_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_driverbuild.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_endpoint_docstrings.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fixed_form.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fortran_doc_comments.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fortran_driver.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fortran_fparser.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fortran_libraries.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_fortran_pipeline.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_gateway_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_generated_python_is_valid.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_golden.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_ir_contract.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_k8s_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_lattice.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_legacy_cpp.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_legacy_fortran.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_locking.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_mcp_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_middleware_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_multifile_cpp.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_native_oracle.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_native_state_contract.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_oracle.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_preprocess_and_config.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_preprocessed_fortran.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_pybind_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_quickstart.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_scalar_ref.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_service_gen.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_shared_libraries.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_structural_invariants.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_suggest.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_verification_config.py +0 -0
- {nativegate-0.1.0 → nativegate-0.1.2}/tests/test_wire.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nativegate
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Make legacy C++/C/Fortran AI-ready and microservice-ready: expose native code as an MCP server, REST API and container
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -33,6 +33,11 @@ Requires-Dist: anyio>=4.0; extra == "test"
|
|
|
33
33
|
|
|
34
34
|
# nativegate — make legacy C++ and Fortran AI-ready and microservice-ready
|
|
35
35
|
|
|
36
|
+
[](https://github.com/ravikings/nativegate/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/nativegate/)
|
|
38
|
+
[](https://pypi.org/project/nativegate/)
|
|
39
|
+
[](https://glama.ai/mcp/servers/ravikings/nativegate)
|
|
40
|
+
|
|
36
41
|
Expose existing C++ and Fortran code to Python as deployable microservices —
|
|
37
42
|
without hand-writing bindings, and without touching the numerics.
|
|
38
43
|
|
|
@@ -41,6 +46,8 @@ bindings, the CMake build, an installable Python package, a FastAPI service,
|
|
|
41
46
|
smoke tests, a numerical regression baseline, and a Dockerfile.
|
|
42
47
|
|
|
43
48
|
```bash
|
|
49
|
+
pip install "nativegate[clang,build]" # from PyPI; needs cmake/ninja + a C/C++/Fortran toolchain for the build step
|
|
50
|
+
|
|
44
51
|
ngate quickstart libraries/geometry/geometry.hpp --name demo --build
|
|
45
52
|
pip install services/demo/dist/*.whl
|
|
46
53
|
```
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# nativegate — make legacy C++ and Fortran AI-ready and microservice-ready
|
|
2
2
|
|
|
3
|
+
[](https://github.com/ravikings/nativegate/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/nativegate/)
|
|
5
|
+
[](https://pypi.org/project/nativegate/)
|
|
6
|
+
[](https://glama.ai/mcp/servers/ravikings/nativegate)
|
|
7
|
+
|
|
3
8
|
Expose existing C++ and Fortran code to Python as deployable microservices —
|
|
4
9
|
without hand-writing bindings, and without touching the numerics.
|
|
5
10
|
|
|
@@ -8,6 +13,8 @@ bindings, the CMake build, an installable Python package, a FastAPI service,
|
|
|
8
13
|
smoke tests, a numerical regression baseline, and a Dockerfile.
|
|
9
14
|
|
|
10
15
|
```bash
|
|
16
|
+
pip install "nativegate[clang,build]" # from PyPI; needs cmake/ninja + a C/C++/Fortran toolchain for the build step
|
|
17
|
+
|
|
11
18
|
ngate quickstart libraries/geometry/geometry.hpp --name demo --build
|
|
12
19
|
pip install services/demo/dist/*.whl
|
|
13
20
|
```
|
|
@@ -60,6 +60,7 @@ from .ir import (
|
|
|
60
60
|
IRSchemaError,
|
|
61
61
|
ModuleIR,
|
|
62
62
|
NativeTypeError,
|
|
63
|
+
is_valid_python_name,
|
|
63
64
|
module_from_dict,
|
|
64
65
|
module_to_dict,
|
|
65
66
|
validate as validate_ir,
|
|
@@ -1241,6 +1242,22 @@ def clean(name: str) -> None:
|
|
|
1241
1242
|
def _scaffold_service(name: str, language: str, force: bool) -> Path:
|
|
1242
1243
|
import shutil
|
|
1243
1244
|
|
|
1245
|
+
# Reject before anything is written: the name becomes a Python package
|
|
1246
|
+
# (services/<name>/python/<name>/), so `specfun-gamma` would fail at
|
|
1247
|
+
# generate time with `from ._native.specfun-gamma import ...` — invalid
|
|
1248
|
+
# syntax caught by the generated-file compile() gate, three commands
|
|
1249
|
+
# and a wasted scaffold after the user typed the name. Saying so here
|
|
1250
|
+
# costs nothing (DEFECTS D9, found on first contact with netlib
|
|
1251
|
+
# specfun, where quickstart defaults the name to the file stem and
|
|
1252
|
+
# `specfun-gamma` is the obvious thing to type).
|
|
1253
|
+
if not is_valid_python_name(name):
|
|
1254
|
+
raise click.ClickException(
|
|
1255
|
+
f"Service name '{name}' is not usable: it becomes a Python package, "
|
|
1256
|
+
"so it must be a valid identifier (letters, digits, underscores, "
|
|
1257
|
+
"not starting with a digit, not a Python keyword). "
|
|
1258
|
+
"Use underscores instead of dashes."
|
|
1259
|
+
)
|
|
1260
|
+
|
|
1244
1261
|
service_dir = Path(SERVICES_DIR) / name
|
|
1245
1262
|
if service_dir.exists():
|
|
1246
1263
|
if not force:
|
|
@@ -1259,7 +1276,11 @@ def _scaffold_service(name: str, language: str, force: bool) -> Path:
|
|
|
1259
1276
|
(service_dir / "python" / name / "__init__.py").write_text(
|
|
1260
1277
|
"# Run `ngate expose` then `ngate generate` to populate this package.\n"
|
|
1261
1278
|
)
|
|
1262
|
-
(service_dir / "pyproject.toml").write_text(
|
|
1279
|
+
(service_dir / "pyproject.toml").write_text(
|
|
1280
|
+
pyproject_gen.generate_pyproject(
|
|
1281
|
+
name, language, has_readme=(service_dir / "README.md").exists()
|
|
1282
|
+
)
|
|
1283
|
+
)
|
|
1263
1284
|
return service_dir
|
|
1264
1285
|
|
|
1265
1286
|
|
|
@@ -1298,7 +1319,11 @@ def _restore_scaffold(service_dir: Path, config: ServiceConfig) -> None:
|
|
|
1298
1319
|
pyproject = service_dir / "pyproject.toml"
|
|
1299
1320
|
if not pyproject.exists():
|
|
1300
1321
|
pyproject.write_text(
|
|
1301
|
-
pyproject_gen.generate_pyproject(
|
|
1322
|
+
pyproject_gen.generate_pyproject(
|
|
1323
|
+
config.name,
|
|
1324
|
+
config.language,
|
|
1325
|
+
has_readme=(service_dir / "README.md").exists(),
|
|
1326
|
+
)
|
|
1302
1327
|
)
|
|
1303
1328
|
click.echo(f"Restored missing {pyproject}")
|
|
1304
1329
|
|
|
@@ -29,7 +29,8 @@ _DEPENDENCIES = {
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def generate_pyproject(
|
|
32
|
-
service_name: str, language: str, needs_numpy: bool = False
|
|
32
|
+
service_name: str, language: str, needs_numpy: bool = False,
|
|
33
|
+
has_readme: bool = False
|
|
33
34
|
) -> str:
|
|
34
35
|
"""The generated service's pyproject.toml.
|
|
35
36
|
|
|
@@ -38,6 +39,15 @@ def generate_pyproject(
|
|
|
38
39
|
import. A C++ service with no such pointer does not get the dependency —
|
|
39
40
|
declaring it unconditionally would put numpy in every image for the
|
|
40
41
|
benefit of the services that do not use it.
|
|
42
|
+
|
|
43
|
+
`has_readme` is True when services/<name>/README.md exists on disk at
|
|
44
|
+
generate time. The `[project] readme` field then carries it, because a
|
|
45
|
+
wheel with no long_description is rejected by `twine check --strict`
|
|
46
|
+
(the whole project builds with that gate on) and lands on PyPI's
|
|
47
|
+
package page with the raw `text/x-rst` heading anyway. When the file
|
|
48
|
+
does not exist the field must stay out: setuptools refuses to build a
|
|
49
|
+
distribution whose declared readme is missing, and a service that has
|
|
50
|
+
never had a README should still build.
|
|
41
51
|
"""
|
|
42
52
|
build_requires = _BUILD_REQUIRES.get(language, _BUILD_REQUIRES["cpp"])
|
|
43
53
|
dependencies = _DEPENDENCIES.get(language, _DEPENDENCIES["cpp"])
|
|
@@ -45,6 +55,8 @@ def generate_pyproject(
|
|
|
45
55
|
build_requires = build_requires.rstrip("]") + ', "numpy"]'
|
|
46
56
|
dependencies = dependencies.rstrip("]") + ', "numpy"]'
|
|
47
57
|
|
|
58
|
+
readme_lines = 'readme = "README.md"\n' if has_readme else ""
|
|
59
|
+
|
|
48
60
|
return f"""[build-system]
|
|
49
61
|
requires = {build_requires}
|
|
50
62
|
build-backend = "scikit_build_core.build"
|
|
@@ -52,7 +64,7 @@ build-backend = "scikit_build_core.build"
|
|
|
52
64
|
[project]
|
|
53
65
|
name = "{service_name}"
|
|
54
66
|
version = "1.0.0"
|
|
55
|
-
requires-python = ">=3.10"
|
|
67
|
+
{readme_lines}requires-python = ">=3.10"
|
|
56
68
|
dependencies = {dependencies}
|
|
57
69
|
|
|
58
70
|
[tool.scikit-build]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nativegate
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Make legacy C++/C/Fortran AI-ready and microservice-ready: expose native code as an MCP server, REST API and container
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -33,6 +33,11 @@ Requires-Dist: anyio>=4.0; extra == "test"
|
|
|
33
33
|
|
|
34
34
|
# nativegate — make legacy C++ and Fortran AI-ready and microservice-ready
|
|
35
35
|
|
|
36
|
+
[](https://github.com/ravikings/nativegate/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/nativegate/)
|
|
38
|
+
[](https://pypi.org/project/nativegate/)
|
|
39
|
+
[](https://glama.ai/mcp/servers/ravikings/nativegate)
|
|
40
|
+
|
|
36
41
|
Expose existing C++ and Fortran code to Python as deployable microservices —
|
|
37
42
|
without hand-writing bindings, and without touching the numerics.
|
|
38
43
|
|
|
@@ -41,6 +46,8 @@ bindings, the CMake build, an installable Python package, a FastAPI service,
|
|
|
41
46
|
smoke tests, a numerical regression baseline, and a Dockerfile.
|
|
42
47
|
|
|
43
48
|
```bash
|
|
49
|
+
pip install "nativegate[clang,build]" # from PyPI; needs cmake/ninja + a C/C++/Fortran toolchain for the build step
|
|
50
|
+
|
|
44
51
|
ngate quickstart libraries/geometry/geometry.hpp --name demo --build
|
|
45
52
|
pip install services/demo/dist/*.whl
|
|
46
53
|
```
|
|
@@ -89,9 +89,11 @@ tests/test_oracle.py
|
|
|
89
89
|
tests/test_preprocess_and_config.py
|
|
90
90
|
tests/test_preprocessed_fortran.py
|
|
91
91
|
tests/test_pybind_gen.py
|
|
92
|
+
tests/test_pyproject_gen.py
|
|
92
93
|
tests/test_quickstart.py
|
|
93
94
|
tests/test_scalar_ref.py
|
|
94
95
|
tests/test_service_gen.py
|
|
96
|
+
tests/test_service_name_validation.py
|
|
95
97
|
tests/test_shared_libraries.py
|
|
96
98
|
tests/test_structural_invariants.py
|
|
97
99
|
tests/test_suggest.py
|
|
@@ -13,7 +13,7 @@ build-backend = "setuptools.build_meta"
|
|
|
13
13
|
|
|
14
14
|
[project]
|
|
15
15
|
name = "nativegate"
|
|
16
|
-
version = "0.1.
|
|
16
|
+
version = "0.1.2"
|
|
17
17
|
description = "Make legacy C++/C/Fortran AI-ready and microservice-ready: expose native code as an MCP server, REST API and container"
|
|
18
18
|
readme = "README.md"
|
|
19
19
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""pyproject_gen: the [project] readme field is conditional on the file existing.
|
|
2
|
+
|
|
3
|
+
Regression for the netlib-specfun contact (DEFECTS D9-D11 record, 2026-09-23):
|
|
4
|
+
a generated service with no README.md shipped a pyproject.toml with no
|
|
5
|
+
long_description at all, and `twine check --strict` rejected every wheel
|
|
6
|
+
built from it. The field must appear only when the file is really there,
|
|
7
|
+
because setuptools refuses a distribution whose declared readme is missing.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from nativegate.generators import pyproject_gen
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_no_readme_field_without_file():
|
|
14
|
+
pyproject = pyproject_gen.generate_pyproject("demo", "fortran")
|
|
15
|
+
assert "readme" not in pyproject
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_readme_field_with_file():
|
|
19
|
+
pyproject = pyproject_gen.generate_pyproject(
|
|
20
|
+
"demo", "fortran", has_readme=True
|
|
21
|
+
)
|
|
22
|
+
assert 'readme = "README.md"' in pyproject
|
|
23
|
+
# still valid TOML-shaped and carries the content type setuptools infers
|
|
24
|
+
assert "[project]" in pyproject
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""D9 regression: dash-named services are rejected at scaffold time, not
|
|
2
|
+
at generate time with invalid generated Python.
|
|
3
|
+
|
|
4
|
+
First contact with netlib specfun (2026-09-23): `ngate quickstart gamma.f
|
|
5
|
+
--name specfun-gamma` scaffolded cleanly, generated
|
|
6
|
+
`from ._native.specfun-gamma import ...` — invalid syntax — and only
|
|
7
|
+
nativegate's generated-file compile() gate refused to write it, three
|
|
8
|
+
commands after the moment the user should have been told.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
from click.testing import CliRunner
|
|
13
|
+
|
|
14
|
+
from nativegate import cli
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture()
|
|
18
|
+
def scratch(tmp_path, monkeypatch):
|
|
19
|
+
monkeypatch.chdir(tmp_path)
|
|
20
|
+
return tmp_path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.mark.parametrize("bad", ["specfun-gamma", "2lib", "class"])
|
|
24
|
+
def test_create_service_rejects_non_identifier_names(scratch, bad):
|
|
25
|
+
result = CliRunner().invoke(cli.main, ["create-service", bad, "--language", "fortran"])
|
|
26
|
+
assert result.exit_code != 0
|
|
27
|
+
assert "Python package" in result.output
|
|
28
|
+
# nothing may have been written
|
|
29
|
+
assert not (scratch / "services").exists()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_quickstart_rejects_dash_named_service_and_explains(tmp_path, monkeypatch):
|
|
33
|
+
monkeypatch.chdir(tmp_path)
|
|
34
|
+
source = tmp_path / "gamma.f"
|
|
35
|
+
source.write_text(" DOUBLE PRECISION FUNCTION DGAMMA(X)\n END\n")
|
|
36
|
+
result = CliRunner().invoke(
|
|
37
|
+
cli.main, ["quickstart", str(source), "--name", "specfun-gamma"]
|
|
38
|
+
)
|
|
39
|
+
assert result.exit_code != 0
|
|
40
|
+
assert "--name specfun_gamma" not in result.output
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_valid_underscored_name_still_scaffolds(scratch):
|
|
44
|
+
result = CliRunner().invoke(
|
|
45
|
+
cli.main, ["create-service", "specfun_gamma", "--language", "fortran"]
|
|
46
|
+
)
|
|
47
|
+
assert result.exit_code == 0, result.output
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|