Skip to content

Make get_by_id a universal pattern or remove it #64

Description

@pederhan

Currently, we support fetching by ID implicitly via get() when an integer argument is passed in to ResourceManager classes:

def get(self, ident: str | int | T, *, required: bool = True) -> T | None:
"""Get a resource by its endpoint identifier (str) or its ID (int).
Args:
ident: The path parameter (id / name / network, per resource).
String arguments are only supported for resources that are
addressed by a non-numeric path parameter (e.g. name, network, hostname).
required: When `True` (default), raise `EntityNotFound` if missing.
Pass `False` to return `T | None` instead.
Raises:
EntityNotFound: If `required` is True and the resource is not found.
Returns:
The resource, or `None` when `required` is False.
"""
obj: T | None = None
try:
obj = self._resolve(ident)
except EntityNotFound:
if required:
raise
return obj

However, some managers, such as HostManager and CommunityManager explicitly implement a get_by_id method:

def get_by_id(self, host_id: int, *, required: bool = True) -> Host | None:
"""Get a host by its numeric id.
Distinct from :meth:`get`: the Host endpoint id-field is the hostname, so
:meth:`get` resolves by name while this resolves by the numeric `id`.
Args:
host_id (int): The numeric id of the host.
required (bool): When True (default), raise EntityNotFound if not found.
Raises:
EntityNotFound: If `required` is True and the host is not found.
"""
obj = self._fetch_by_field("id", host_id)
if required and obj is None:
raise EntityNotFound(f"Host with id {host_id!r} not found.")
return obj

mreg-api/mreg_api/managers.py

Lines 2094 to 2117 in b24a514

def get_by_id(
self, community_id: int, network: str | int | Network, *, required: bool = True
) -> Community | None:
"""Get a community by ID within a network.
Args:
community_id (int): The community ID to look up.
network (str | int | Network): Network reference (address, ID, or Network instance).
required (bool): When True (default), raise EntityNotFound if not found.
Raises:
EntityNotFound: If `required` is True and the community is not found.
"""
community: Community | None = None
nw_addr = self._resolve_network_address(network)
try:
# Attempt to directly fetch the community
community = self._client.get_typed(
Endpoint.NetworkCommunity.with_params(nw_addr, community_id), Community
)
except EntityNotFound:
if required:
raise EntityNotFound(f"Community {community_id!r} not found.") from None
return community

This inconsistency between the managers is an anti-pattern that I would like to be without. get() should be either be implemented in a way that makes get_by_id redundant, or get_by_id should be made a universal pattern across all managers.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions