Change python package namespace sub namespaces to list

This commit is contained in:
jakob.scheid committed 2026-04-09 16:08:07 +02:00
1 parent 512a07a773
commit 9e524bec03
7 files changed
+130 -66

No files matched your search

+68 -17
View File
@@ -13,8 +13,9 @@
# limitations under the License.
from __future__ import annotations
from ...exceptions import InvalidNamespaceError, NamespaceNotFoundError
from ...exceptions import InvalidNamespaceError, NamespaceNotFoundError, NamespaceExistsError
from ...utils import assert_that_is_instance
from typing import Union, TypeAlias, Dict, List
__all__ = [
'PythonNamespace',
@@ -40,6 +41,8 @@ class PythonNamespace:
def __repr__(self) -> str:
return f'{type(self).__name__}({self.name!r})'
PythonPackageNamespaceDictType: TypeAlias = Dict[str, Union[str, 'PythonPackageNamespaceDictType']]
class PythonPackageNamespace(PythonNamespace):
'''
A subclass of ``PythonNamespace`` for python package namespaces.
@@ -50,15 +53,27 @@ class PythonPackageNamespace(PythonNamespace):
:type sub_namespaces: list[PythonNamespace]
'''
def __init__(self, name: str, sub_namespaces: dict[str, PythonNamespace]) -> None:
def __init__(self, name: str, sub_namespaces: List[PythonNamespace]) -> None:
assert_that_is_instance(sub_namespaces, list)
super().__init__(name)
self.sub_namespaces = sub_namespaces
self._sub_namespaces = sub_namespaces
def namespace(self, sub_namespaces: list[str]) -> PythonNamespace:
def namespace(self, sub_namespaces: List[str]) -> PythonNamespace:
'''
Returns the namespace object with a specific identifier, such as
``['package', 'subpackage', 'module']``.
:param sub_namespaces: The identifier of the namespace.
:type sub_namespaces: list[str]
:raises InvalidNamespaceError: If the namespace identifier is
invalid.
:raises NamespaceNotFoundError: If the namespace does not exist.
:return: The namespace.
:rtype: PythonNamespace
'''
if not sub_namespaces:
@@ -68,11 +83,7 @@ class PythonPackageNamespace(PythonNamespace):
if not sn:
raise InvalidNamespaceError('invalid namespace')
# check whether the sub-namespace exists
if sub_namespaces[0] not in self.sub_namespaces:
raise NamespaceNotFoundError('no such namespace', namespace_identifier = sub_namespaces[0])
sub_namespace = self.sub_namespaces[sub_namespaces[0]]
sub_namespace = self.__getitem__(sub_namespaces[0])
# package namespace
if isinstance(sub_namespace, PythonPackageNamespace):
@@ -82,8 +93,8 @@ class PythonPackageNamespace(PythonNamespace):
# module namespace
else:
return sub_namespace
def _sub_namespaces_names(self, package: PythonPackageNamespace) -> list[str]:
def _sub_namespaces_names(self, package: PythonPackageNamespace) -> PythonPackageNamespaceDictType:
'''
Returns the names of all sub-namespaces of the specified package
namespace and keeps the package structure.
@@ -92,21 +103,21 @@ class PythonPackageNamespace(PythonNamespace):
:type package: PythonPackageNamespace
:return: The names if all sub-namespaces.
:rtype: list[str]
:rtype: PythonPackageNamespaceDictType
'''
return {
n: self._sub_namespaces_names(sn) if isinstance(sn, PythonPackageNamespace) else sn.name
for n, sn in package.sub_namespaces.items()
sn.name: self._sub_namespaces_names(sn) if isinstance(sn, PythonPackageNamespace) else sn.name
for sn in package._sub_namespaces
}
def sub_namespace_names(self) -> list[str]:
def sub_namespace_names(self) -> PythonPackageNamespaceDictType:
'''
Returns the names of all sub-namespaces and keeps the package
structure.
:return: The names if all sub-namespaces.
:rtype: list[str]
:rtype: PythonPackageNamespaceDictType
'''
return self._sub_namespaces_names(self)
@@ -121,7 +132,47 @@ class PythonPackageNamespace(PythonNamespace):
return value.sub_namespace_names() == self.sub_namespace_names()
def __repr__(self) -> str:
return type(self).__name__ + repr((self.name, self.sub_namespaces))
return type(self).__name__ + repr((self.name, self._sub_namespaces))
def __getitem__(self, name: str) -> PythonNamespace:
'''
Returns a namespace with the specified name.
:param name: The name of the namespace
:type name: str
:raises NamespaceNotFoundError: If the namespace does not exist.
:return: The namespace
:rtype: PythonNamespace
'''
for sub in self._sub_namespaces:
if sub.name == name:
return sub
raise NamespaceNotFoundError('no such namespace', namespace_identifier = name)
def add(self, namespace: PythonNamespace) -> None:
'''
Adds a namespace.
:param namespace: The namespace to add.
:type namespace: PythonNamespace
:raises NamespaceExistsError: If a namespace with the name of the
namespace that is attempted to add
already exists.
'''
try:
self.__getitem__(namespace.name)
raise NamespaceExistsError('namespace already exists', namespace_identifier = namespace.name)
except NamespaceNotFoundError:
self._sub_namespaces.append(namespace)
@property
def sub_namespaces(self) -> List[PythonNamespace]:
return self._sub_namespaces
class PythonModuleNamespace(PythonNamespace):
'''