Skip to content

Namespaces

plateforme.core.namespaces

This module provides utilities for managing namespaces within the Plateforme framework.

Namespace

Namespace(name: str)

Bases: Representation

A namespace placeholder for packages within the Plateforme framework.

A namespace is a container for packages. It provides a way to group related packages together and manage their resources, routes, and API endpoints.

Attributes:

Name Type Description
_impls dict[Plateforme | None, NamespaceImpl]

The registered namespace implementations as a dictionary mapping the application context to the namespace implementation.

name str

The name of the namespace that is unique within the entire runtime environment. It can be None for the default namespace, otherwise it must be a snake case formatted string of max 63 characters.

Initialize a namespace.

Note

The import_namespace method should be used to retrieve a namespace instance based on the provided name.

Source code in .venv/lib/python3.12/site-packages/plateforme/core/namespaces.py
def __init__(self, name: str):
    """Initialize a namespace.

    Note:
        The `import_namespace` method should be used to retrieve a
        namespace instance based on the provided name.
    """
    # Validate namespace name
    if name and (
        not re.match(RegexPattern.ALIAS, name)
        or len(name) > 63
    ):
        raise PlateformeError(
            f"Invalid namespace provided name {name!r}, it must be a "
            f"snake case formatted string of max 63 characters or `''`.",
            code='namespace-invalid-config',
        )

    object.__setattr__(self, '_impls', {})
    object.__setattr__(self, 'name', name)

impl property

The current namespace implementation based on the app context.

A read-only property that returns the namespace implementation based on the application context. If no context is available, it returns the namespace default implementation. Otherwise, it raises an error if the namespace implementation is not available in the current application context.

NamespaceImpl

NamespaceImpl(
    namespace: Namespace,
    context: Plateforme | None,
    *,
    settings: NamespaceSettings | None = None,
    auto_generated: bool = False,
)

Bases: Proxy[Namespace]

A namespace implementation proxy class.

It defines the implementation details of a namespace within the Plateforme framework. It extends the Proxy class and adds additional information about the namespace.

Attributes:

Name Type Description
context Plateforme | None

The application context associated with the namespace implementation.

packages dict[str, PackageImpl]

A dictionary of packages implemented within the namespace.

settings NamespaceSettings

The namespace settings to use for the implementation.

auto_generated bool

Whether the namespace implementation is auto-generated and should not be persisted when removing dependent packages.

api APIManager

The API manager of the namespace implementation.

Initialize a namespace implementation proxy instance.

Parameters:

Name Type Description Default
namespace Namespace

The namespace instance to proxy.

required
context Plateforme | None

The application context to associate with the namespace implementation.

required
settings NamespaceSettings | None

The namespace settings to use. Defaults to an empty NamespaceSettings object.

None
auto_generated bool

Whether the namespace implementation is auto-generated and should not be persisted when removing dependent packages. Defaults to False.

False
Source code in .venv/lib/python3.12/site-packages/plateforme/core/namespaces.py
def __init__(
    self,
    namespace: Namespace,
    context: 'Plateforme | None',
    *,
    settings: NamespaceSettings | None = None,
    auto_generated: bool = False,
):
    """Initialize a namespace implementation proxy instance.

    Args:
        namespace: The namespace instance to proxy.
        context: The application context to associate with the namespace
            implementation.
        settings: The namespace settings to use. Defaults to an empty
            `NamespaceSettings` object.
        auto_generated: Whether the namespace implementation is
            auto-generated and should not be persisted when removing
            dependent packages. Defaults to ``False``.
    """
    super().__init__(namespace)
    object.__setattr__(self, 'context', context)
    object.__setattr__(self, 'packages', {})
    object.__setattr__(self, 'auto_generated', auto_generated)

    # Merge default implementation settings using "getattr" method to
    # avoid circular import issues when the default implementation is
    # initialized within the namespace module.
    settings = settings or NamespaceSettings()
    default_impl: NamespaceImpl | None = namespace._impls.get(None, None)
    if default_impl is not None:
        settings = merge_settings(default_impl.settings, settings)
    object.__setattr__(self, 'settings', settings)

    self.setup_api(reset=True)

    namespace._impls[context] = self

namespace property

namespace: Namespace

The namespace associated with the implementation.

alias property

alias: str

The namespace alias.

It is used to to define which database schema should store its resources in an application. Multiple namespaces can share the same alias within an application. It must be formatted to snake case and defaults to the namespace name.

Examples:

  • my_namespace

path property

path: str

The namespace API route path.

It specifies the API route path of the namespace within an application.

Examples:

  • /my-namespace

slug property

slug: str

The namespace slug.

It is used to define which URL path should be used to access the namespace resources in an API. Multiple namespaces can share the same slug within an application. It must be formatted to kebab case and defaults to the kebab case of the namespace name.

Examples:

  • my-namespace for my_namespace

title property

title: str | None

The namespace human-readable title.

It is used to display the namespace verbose name within an application. It defaults to the titleized version of the namespace alias.

Examples:

  • My Namespace for my_namespace

setup_api

setup_api(*, reset: bool = False) -> None

Setup the namespace API manager.

Parameters:

Name Type Description Default
reset bool

Whether to reset the namespace API manager, i.e. clear all existing routes from current router. Defaults to False.

False
Source code in .venv/lib/python3.12/site-packages/plateforme/core/namespaces.py
def setup_api(self, *, reset: bool = False) -> None:
    """Setup the namespace API manager.

    Args:
        reset: Whether to reset the namespace API manager, i.e. clear all
            existing routes from current router. Defaults to ``False``.
    """
    # Resolve settings
    settings_base: Settings | NamespaceSettings = \
        self.context.settings if self.context else self.settings
    settings_api = merge_settings(
        APISettings(),
        self.context.settings.api if self.context else None,
        self.settings.api,
    )

    # Resolve base configuration
    debug = self.context.settings.debug if self.context else False
    title = self.title or settings_base.title
    summary = self.settings.summary or settings_base.summary
    description = self.settings.description or settings_base.description
    version = self.settings.version or settings_base.version
    terms_of_service = self.settings.terms_of_service \
        or settings_base.terms_of_service
    contact = self.settings.contact or settings_base.contact
    license_info = self.settings.license or settings_base.license
    deprecated = self.settings.deprecated or settings_base.deprecated

    # Build configuration dictionary
    config: dict[str, Any] = dict(
        debug=debug,
        title=title,
        summary=summary,
        description=description,
        version=version,
        terms_of_service=terms_of_service,
        contact=contact.model_dump() if contact else None,
        license_info=license_info.model_dump() if license_info else None,
        deprecated=deprecated,
        **settings_api.model_dump(),
    )

    # Setup manager and include current router if no reset
    router = None
    if not reset:
        router = self.api.router
    object.__setattr__(self, 'api', APIManager(**config))
    if not reset:
        assert router is not None
        self.api.include_router(router)

mount

mount(
    *names: str,
    force: bool = False,
    raise_errors: bool = True,
    **overrides: Unpack[APIBaseRouterConfigDict],
) -> None

Mount given packages into the namespace API manager.

Parameters:

Name Type Description Default
*names str

A list of package module names to mount into the application namespace API manager.

()
force bool

Whether to force mount the packages even if they are already mounted. This will not raise an error if a package is already mounted, otherwise it will replace the existing package router with a new one. Defaults to False.

False
raise_errors bool

Whether to raise errors or fail silently if a package is already mounted within the API manager. Defaults to True.

True
**overrides Unpack[APIBaseRouterConfigDict]

Additional router configuration keyword arguments to override the default router configuration when including the package routers.

{}
Source code in .venv/lib/python3.12/site-packages/plateforme/core/namespaces.py
def mount(
    self,
    *names: str,
    force: bool = False,
    raise_errors: bool = True,
    **overrides: Unpack[APIBaseRouterConfigDict],
) -> None:
    """Mount given packages into the namespace API manager.

    Args:
        *names: A list of package module names to mount into the
            application namespace API manager.
        force: Whether to force mount the packages even if they are already
            mounted. This will not raise an error if a package is already
            mounted, otherwise it will replace the existing package router
            with a new one. Defaults to ``False``.
        raise_errors: Whether to raise errors or fail silently if a
            package is already mounted within the API manager.
            Defaults to ``True``.
        **overrides: Additional router configuration keyword arguments to
            override the default router configuration when including the
            package routers.
    """
    packages = self._validate_package_names(
        *names, raise_errors=raise_errors
    )

    # Mount packages
    for package in packages:
        for route in self.api.routes:
            if not isinstance(route, APIBaseRoute):
                continue
            route_package, *_ = parse_unique_id(route.unique_id)
            if route_package != package.name:
                continue
            if not force:
                if not raise_errors:
                    continue
                raise PlateformeError(
                    f"Package {package.name!r} is already mounted in the "
                    f"namespace {self.name!r} within application "
                    f"{str(self.context)!r}.",
                    code='namespace-invalid-package',
                )
            self.api.routes.remove(route)

        router = package._create_router()
        self.api.include_router(router, **overrides)

unmount

unmount(*names: str, raise_errors: bool = True) -> None

Unmount given packages from the namespace API manager.

Parameters:

Name Type Description Default
*names str

A list of package module names to unmount from the application namespace API manager.

()
raise_errors bool

Whether to raise errors or fail silently if a package is not mounted within the API manager. Defaults to True.

True
Source code in .venv/lib/python3.12/site-packages/plateforme/core/namespaces.py
def unmount(
    self,
    *names: str,
    raise_errors: bool = True,
) -> None:
    """Unmount given packages from the namespace API manager.

    Args:
        *names: A list of package module names to unmount from the
            application namespace API manager.
        raise_errors: Whether to raise errors or fail silently if a
            package is not mounted within the API manager.
            Defaults to ``True``.
    """
    packages = self._validate_package_names(
        *names, raise_errors=raise_errors
    )

    # Unmount packages
    for package in packages:
        has_routes = False
        for route in self.api.routes:
            if not isinstance(route, APIBaseRoute):
                continue
            route_package, *_ = parse_unique_id(route.unique_id)
            if route_package == package.name:
                self.api.routes.remove(route)
                has_routes = True
        if not has_routes and raise_errors:
            raise PlateformeError(
                f"Package {package.name!r} is not mounted in the "
                f"namespace {self.name!r} within application "
                f"{str(self.context)!r}.",
                code='namespace-invalid-package',
            )