Source code for fitrequest.method_config_group

import logging
from importlib.metadata import PackageNotFoundError, version

from pydantic import BaseModel, ConfigDict, Field, model_validator
from typing_extensions import Self

from fitrequest.auth import Auth
from fitrequest.fit_var import ValidFitVar
from fitrequest.method_config import MethodConfig
from fitrequest.method_config_family import FamilyTemplates, MethodConfigFamily
from fitrequest.method_decorator import ValidMethodDecorator

logger = logging.getLogger(__name__)


[docs] class MethodConfigGroup(BaseModel): """Describes the configuration of a set of methods""" client_name: str """Name of the client.""" version: str = '' """Version of the client. If not provided FitRequest tries to retrieve the version from the python package.""" method_docstring: str = '' """ Default Jinja template for the generated method. The default variable declaration ``{{my_var}}`` is replaced by ``{my_var}``. See: https://jinja.palletsprojects.com/en/stable/ """ method_decorators: list[ValidMethodDecorator] = Field(default_factory=list) """Default decorators applied to the generated method.""" base_url: ValidFitVar = None """Default base URL for the generated method.""" auth: Auth | None = None """Authentication object used by generated methods.""" family_name_templates: FamilyTemplates | None = None """ These name templates are used to generate family names. Be cautious when overriding these default values with custom templates, as doing so - especially if the custom templates do not utilize all the requested variables for naming - could lead to unexpected errors. Override these templates with care. """ method_config_list: list[MethodConfig | MethodConfigFamily] = Field(default_factory=list) """List of ``MethodConfig`` and ``MethodConfigFamily`` objects representing the methods to be generated.""" model_config = ConfigDict(arbitrary_types_allowed=True) @model_validator(mode='after') def update_family_templates(self) -> Self: """Update families with default group template.""" if self.family_name_templates is not None: for family in self.method_config_list: if isinstance(family, MethodConfigFamily): family.name_templates = self.family_name_templates return self @model_validator(mode='after') def validate_methods(self) -> Self: """ Ensures the list contains only MethodConfig instances by expanding any MethodConfigFamily elements into their individual MethodConfig members. """ validated_methods = [] for item in self.method_config_list: if isinstance(item, MethodConfigFamily): validated_methods.extend(item.members) else: validated_methods.append(item) self.method_config_list = sorted(validated_methods, key=lambda x: x.name) return self @model_validator(mode='after') def update_method_vars(self) -> Self: """ Update self and method_config variables with the priority below: 1/ method_config vars 2/ method_config_list vars """ for method_config in self.method_config_list or []: method_config.base_url = method_config.base_url or self.base_url method_config.docstring = method_config.docstring or self.method_docstring method_config.decorators = method_config.decorators or self.method_decorators method_config.validate_doctring() return self @model_validator(mode='after') def validate_version(self) -> Self: if self.version: return self try: self.version = version(self.client_name) except PackageNotFoundError: logger.warning( 'Cannot retrieve package version, either your package is not named ' 'as your client_name attribute, or it is not installed.', extra={'client_name': self.client_name}, ) self.version = '{version}' return self