• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

andy-goellner / pco-python-sdk / 13222372648

09 Feb 2025 04:30AM UTC coverage: 84.222% (+2.4%) from 81.798%
13222372648

push

github

web-flow
feat: adding inclusions support (#10)

33 of 33 new or added lines in 4 files covered. (100.0%)

1 existing line in 1 file now uncovered.

395 of 469 relevant lines covered (84.22%)

2.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.71
/src/planning_center_python/models/pco_object.py
1
from collections.abc import Mapping
3✔
2
from typing import Any, ClassVar, Optional, cast
3✔
3

4
from planning_center_python.errors import (
3✔
5
    InvalidParamsError,
6
    InvalidRequestError,
7
    NoAttributesDefinedError,
8
)
9
from planning_center_python.types.abstract_pco_object import AbstractPCOObject
3✔
10
from planning_center_python.types.inclusions import Inclusion, InclusionDefinition
3✔
11
from planning_center_python.types.relationships import (
3✔
12
    Relationship,
13
    RelationshipDefinition,
14
)
15

16

17
class PCOObject(AbstractPCOObject):
3✔
18
    """Base class object from which all Planning Center objects should inherit from"""
19

20
    OBJECT_TYPE: ClassVar[str] = "BaseClass"
3✔
21
    OBJECT_URL: ClassVar[str] = ""
3✔
22
    RELATIONSHIPS: ClassVar[list[RelationshipDefinition]] = []
3✔
23
    INCLUSION_DEFINITIONS: ClassVar[list[InclusionDefinition]] = []
3✔
24

25
    def __call__(
3✔
26
        self,
27
        data: Mapping[str, Any] = {},
28
        id: Optional[str] = None,
29
        included_data: list[Mapping[str, Any]] = [],
30
    ) -> Any:
UNCOV
31
        self.__init__(data=data, id=id)
×
32

33
    def __init__(
3✔
34
        self,
35
        data: Mapping[str, Any] = {},
36
        id: Optional[str] = None,
37
        included_data: list[Mapping[str, Any]] = [],
38
    ):
39
        self._data = data
3✔
40
        self._id = id or data.get("id")
3✔
41
        self._type = data.get("type") or self.OBJECT_TYPE
3✔
42
        self._validate()
3✔
43
        self.attributes = data.get("attributes")
3✔
44
        self.relationships = self._init_relationships(
3✔
45
            cast(Mapping[str, Any], data.get("relationships"))
46
        )
47
        self.included = self._init_inclusions(included_data)
3✔
48

49
    def get_attribute(self, name: str) -> Any:
3✔
50
        if not self.attributes:
3✔
51
            raise NoAttributesDefinedError
3✔
52
        return self.attributes.get(name)
3✔
53

54
    def get_relationship(self, key: str) -> AbstractPCOObject | None:
3✔
55
        return next(
3✔
56
            (r.class_instance for r in self.relationships if r.key == key),
57
            None,
58
        )
59

60
    def get_inclusion(self, key: str) -> AbstractPCOObject | None:
3✔
61
        return next(
3✔
62
            (r.class_instance for r in self.included if r.key == key),
63
            None,
64
        )
65

66
    def _instance_url(self) -> str:
3✔
67
        if not self.id:
3✔
68
            raise InvalidRequestError(
×
69
                "Cannot determine instance url without a valid id"
70
            )
71
        return "%s/%s" % (self._object_url(), self.id)
3✔
72

73
    def _validate(self):
3✔
74
        if not self.id:
3✔
75
            raise InvalidParamsError(self, "id")
3✔
76
        if not self.type:
3✔
77
            raise InvalidParamsError(self, "type")
×
78
        if self.type != self.OBJECT_TYPE:
3✔
79
            raise InvalidParamsError(self, "type", "Class types do not match")
3✔
80

81
    def _init_relationships(
3✔
82
        self, object_data: Mapping[str, Any] | None
83
    ) -> list[Relationship]:
84
        built_relationships: list[Relationship] = []
3✔
85
        if object_data:
3✔
86
            for definition in self.RELATIONSHIPS:
3✔
87
                relation = object_data.get(definition["key"])
3✔
88
                if relation:
3✔
89
                    relation_id = relation["data"]["id"]
3✔
90
                    klass_instance = definition["klass"](id=relation_id)
3✔
91
                    built_relationships.append(
3✔
92
                        Relationship(definition["key"], klass_instance)
93
                    )
94
                    self.__setattr__(definition["method"], klass_instance)
3✔
95
        return built_relationships
3✔
96

97
    def _init_inclusions(
3✔
98
        self, included_data: list[Mapping[str, Any]] | None
99
    ) -> list[Inclusion]:
100
        built_inclusions: list[Inclusion] = []
3✔
101
        if included_data:
3✔
102
            for inclusion in included_data:
3✔
103
                definition = self._find_definition_from_type(
3✔
104
                    self.INCLUSION_DEFINITIONS, inclusion["type"]
105
                )
106
                if definition:
3✔
107
                    klass_instance = definition["klass"](data=inclusion)
3✔
108
                    built_inclusions.append(
3✔
109
                        Inclusion(definition["key"], klass_instance)
110
                    )
111
                    self.__setattr__(definition["method"], klass_instance)
3✔
112

113
        return built_inclusions
3✔
114

115
    @staticmethod
3✔
116
    def _find_definition_from_type(
3✔
117
        definitions: list[RelationshipDefinition | InclusionDefinition], def_type: str
118
    ) -> InclusionDefinition | RelationshipDefinition | None:
119
        return next((dfn for dfn in definitions if dfn["type"] == def_type), None)
3✔
120

121
    @property
3✔
122
    def id(self) -> str | None:
3✔
123
        return self._id
3✔
124

125
    @property
3✔
126
    def type(self) -> str | None:
3✔
127
        return self._type
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc