From 0f65e76376715100e7040c6539366739fcf6b7e7 Mon Sep 17 00:00:00 2001 From: Ramesh Padmanabhaiah <22363102+codeforester@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:56:29 -0700 Subject: [PATCH] Add reserved experimental namespace --- CHANGELOG.md | 2 ++ docs/api-stability.md | 8 ++++---- lib/python/base_cli/__init__.py | 13 ++++++++++++- lib/python/base_cli/experimental.py | 8 ++++++++ tests/test_api_stability.py | 1 + tests/test_public_api.py | 4 ++++ 6 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 lib/python/base_cli/experimental.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 4627684..57d2d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,8 @@ the API stability policy and migration guide before upgrading from `0.3.x`. - Add the MkDocs documentation site configuration, strict documentation checks, and GitHub Pages deployment workflow. +- Add the importable, intentionally empty `base_cli.experimental` namespace for + future preview APIs without expanding the stable API surface. ### Changed diff --git a/docs/api-stability.md b/docs/api-stability.md index 67363f1..0df27f9 100644 --- a/docs/api-stability.md +++ b/docs/api-stability.md @@ -27,10 +27,10 @@ and history implementation details are not stable machine interfaces unless a separate contract document says otherwise. Consumers that need automation should select the JSON or record protocol contracts. -`base_cli.experimental` is reserved for preview APIs. No experimental symbols -are currently shipped. A future preview must live under that namespace, be -labelled experimental in its documentation, and must not be re-exported from -the stable facade until it is promoted. +The importable `base_cli.experimental` module is reserved for preview APIs. No +experimental symbols are currently shipped. A future preview must live under +that namespace, be labelled experimental in its documentation, and must not +be re-exported from the stable facade until it is promoted. ## Versioning and compatibility diff --git a/lib/python/base_cli/__init__.py b/lib/python/base_cli/__init__.py index af8ee59..6fa0e8c 100644 --- a/lib/python/base_cli/__init__.py +++ b/lib/python/base_cli/__init__.py @@ -30,7 +30,17 @@ def _resolve_version() -> str: __version__ = _resolve_version() -from . import command_filters, command_protocol, deprecations, extensions, history, integrations, json_contracts, testing +from . import ( + command_filters, + command_protocol, + deprecations, + experimental, + extensions, + history, + integrations, + json_contracts, + testing, +) from .attachment import ( AttachmentAdapter, AttachmentContextFactory, @@ -182,6 +192,7 @@ def _resolve_version() -> str: "command_matches", "command_protocol", "deprecations", + "experimental", "json_contracts", "JSON_CONTRACT_VERSION", "JSON_ERROR_SCHEMA", diff --git a/lib/python/base_cli/experimental.py b/lib/python/base_cli/experimental.py new file mode 100644 index 0000000..3c3c2b6 --- /dev/null +++ b/lib/python/base_cli/experimental.py @@ -0,0 +1,8 @@ +"""Preview APIs under active development. + +Names in this module are subject to change without notice. They will not be +re-exported from the stable :mod:`base_cli` facade until promoted. See +``docs/api-stability.md`` for the promotion policy. +""" + +__all__: list[str] = [] diff --git a/tests/test_api_stability.py b/tests/test_api_stability.py index 1636605..46bc548 100644 --- a/tests/test_api_stability.py +++ b/tests/test_api_stability.py @@ -55,6 +55,7 @@ "command_matches", "command_protocol", "deprecations", + "experimental", "json_contracts", "JSON_CONTRACT_VERSION", "JSON_ERROR_SCHEMA", diff --git a/tests/test_public_api.py b/tests/test_public_api.py index 626e96c..0f88d26 100644 --- a/tests/test_public_api.py +++ b/tests/test_public_api.py @@ -12,6 +12,7 @@ command_protocol, config, deprecations, + experimental, history, json_contracts, lifecycle_options, @@ -62,6 +63,7 @@ def test_facade_exports_supported_modules_functions_and_types(self) -> None: "command_filters", "command_matches", "command_protocol", + "experimental", "dumps_record", "dumps_records", "get_command_app", @@ -83,6 +85,7 @@ def test_facade_exports_supported_modules_functions_and_types(self) -> None: self.assertIs(base_cli.typer, typer) self.assertIs(base_cli.json_contracts, json_contracts) self.assertIs(base_cli.deprecations, deprecations) + self.assertIs(base_cli.experimental, experimental) self.assertTrue(issubclass(base_cli.ConfigurationError, ValueError)) def test_module_all_surfaces_are_explicit(self) -> None: @@ -160,6 +163,7 @@ def test_module_all_surfaces_are_explicit(self) -> None: }, ) self.assertEqual(set(deprecations.__all__), {"BaseCliDeprecationWarning", "deprecated"}) + self.assertEqual(experimental.__all__, []) self.assertEqual(base_cli.testing.__all__, ["invoke"]) def test_entry_points_have_docstrings(self) -> None: