ritten-python-sdk 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ """
2
+ Ritten SDK Organizations Resource.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ import httpx
9
+ from typing import Dict, Any
10
+
11
+ from ritten.resources.resource import Resource
12
+
13
+
14
+ class Organizations(Resource):
15
+ """
16
+ Handles all interactions with the Ritten API `/organizations` endpoints.
17
+ """
18
+
19
+ def __init__(self, client: httpx.Client):
20
+ self._client = client
21
+ self._base_path = "/organizations"
22
+
23
+ def list(
24
+ self,
25
+ limit: int = 20,
26
+ offset: int = 0,
27
+ search: str | None = None,
28
+ sort_by: str | None = None,
29
+ organization_type_ids: list[str] | None = None,
30
+ assigned_user_ids: list[str] | None = None,
31
+ ) -> Dict[str, Any]:
32
+ """Lists active organizations."""
33
+ params = {"limit": limit, "offset": offset}
34
+ if search:
35
+ params["search"] = search
36
+ if sort_by:
37
+ params["sortBy"] = sort_by
38
+ if organization_type_ids:
39
+ params["organizationTypeIds"] = str(organization_type_ids)
40
+ if assigned_user_ids:
41
+ params["assignedUserIds"] = str(assigned_user_ids)
42
+ return self._client.get(self._base_path, params=params).json()
43
+
44
+ def get(self, id: str) -> Dict[str, Any]:
45
+ """Retrieves a single active organization by its ID."""
46
+ return self._client.get(f"{self._base_path}/{id}").json()
47
+
48
+ def create(self, payload: Dict[str, Any]) -> Dict[str, Any]:
49
+ """Creates a new organization."""
50
+ return self._client.post(self._base_path, json=payload).json()
51
+
52
+ def update(self, id: str, payload: Dict[str, Any]) -> None | Dict[str, Any]:
53
+ """Updates an active organization by ID."""
54
+ return self._client.patch(f"{self._base_path}/{id}", json=payload).json()
55
+
56
+ def members(
57
+ self,
58
+ organization_id: str,
59
+ limit: int = 20,
60
+ offset: int = 0,
61
+ ) -> Dict[str, Any]:
62
+ """Lists members of an active organization."""
63
+ params = {"limit": limit, "offset": offset}
64
+ return self._client.get(
65
+ f"{self._base_path}/{organization_id}/members", params=params
66
+ ).json()
@@ -0,0 +1,115 @@
1
+ """
2
+ Ritten SDK Patients Resource.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ import httpx
9
+ from typing import Dict, Any
10
+
11
+ from ritten.resources.resource import Resource
12
+
13
+
14
+ class Patients(Resource):
15
+ """
16
+ Handles all interactions with the Ritten API `/patients` endpoints.
17
+ """
18
+
19
+ def __init__(self, client: httpx.Client):
20
+ self._client = client
21
+ self._base_path = "/patients"
22
+
23
+ def list(
24
+ self,
25
+ program_status: str,
26
+ limit: int = 20,
27
+ offset: int = 0,
28
+ ) -> Dict[str, Any]:
29
+ """Lists patients in a clinic."""
30
+
31
+ params = {
32
+ "programStatus": program_status,
33
+ "limit": limit,
34
+ "offset": offset,
35
+ }
36
+
37
+ return self._client.get(self._base_path, params=params).json()
38
+
39
+ def get(self, id: str) -> Dict[str, Any]:
40
+ """Retrieves a single patient by their Ritten ID."""
41
+ return self._client.get(f"{self._base_path}/{id}").json()
42
+
43
+ def create(self, payload: Dict[str, Any]) -> Dict[str, Any]:
44
+ """Creates a new patient record."""
45
+ return self._client.post(self._base_path, json=payload).json()
46
+
47
+ def update(self, id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
48
+ """Updates a patient by ID."""
49
+ return self._client.patch(
50
+ f"{self._base_path}/{id}",
51
+ json=payload,
52
+ ).json()
53
+
54
+ def get_by_external_id(self, external_id: str) -> Dict[str, Any]:
55
+ """Retrieves a patient using an external system ID."""
56
+ return self._client.get(f"{self._base_path}/external/{external_id}").json()
57
+
58
+ # --- Clinical Data ---
59
+
60
+ def record_vitals(self, id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
61
+ """Records a single vital observation for the patient.
62
+ Units are fixed by observation and measurement type; do not include units in the request body.
63
+ """
64
+ return self._client.post(
65
+ f"{self._base_path}/{id}/vitals",
66
+ json=payload,
67
+ ).json()
68
+
69
+ # --- Relationships ---
70
+
71
+ def list_relationships(self, id: str) -> Dict[str, Any]:
72
+ """Lists a patient's relationships."""
73
+ return self._client.get(f"{self._base_path}/{id}/relationships").json()
74
+
75
+ def create_relationship(self, id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
76
+ """Creates a new patient relationship."""
77
+ return self._client.post(
78
+ f"{self._base_path}/{id}/relationships",
79
+ json=payload,
80
+ ).json()
81
+
82
+ def update_relationship(
83
+ self, patient_id: str, relationship_id: str, payload: Dict[str, Any]
84
+ ) -> Dict[str, Any]:
85
+ """Updates a specific patient relationship."""
86
+ return self._client.patch(
87
+ f"{self._base_path}/{patient_id}/relationships/{relationship_id}",
88
+ json=payload,
89
+ ).json()
90
+
91
+ def delete_relationship(self, patient_id: str, relationship_id: str) -> None:
92
+ """Deletes a patient relationship."""
93
+ self._client.delete(
94
+ f"{self._base_path}/{patient_id}/relationships/{relationship_id}",
95
+ )
96
+
97
+ # --- Chart Documents ---
98
+
99
+ def attach_document(
100
+ self, patient_id: str, payload: Dict[str, Any]
101
+ ) -> Dict[str, Any]:
102
+ """Attaches a document to a patient chart."""
103
+ return self._client.post(
104
+ f"{self._base_path}/{patient_id}/attachments",
105
+ json=payload,
106
+ ).json()
107
+
108
+ def update_document(
109
+ self, patient_id: str, attachment_id: str, payload: Dict[str, Any]
110
+ ) -> Dict[str, Any]:
111
+ """Updates the title or type of a document on a patient chart. Omitting a field will leave it unchanged."""
112
+
113
+ return self._client.patch(
114
+ f"{self._base_path}/{patient_id}/attachments/{attachment_id}", json=payload
115
+ ).json()
@@ -0,0 +1,51 @@
1
+ """
2
+ Ritten SDK Programs Resource.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ import httpx
9
+ from typing import Dict, Any
10
+
11
+ from ritten.resources.resource import Resource
12
+
13
+
14
+ class Programs(Resource):
15
+ """
16
+ Handles all interactions with the Ritten API `/programs` endpoints.
17
+ """
18
+
19
+ def __init__(self, client: httpx.Client):
20
+ self._client = client
21
+ self._base_path = "/programs"
22
+
23
+ def list(
24
+ self,
25
+ limit: int = 20,
26
+ offset: int = 0,
27
+ search: str | None = None,
28
+ programType: str | None = None,
29
+ facility_id: str | None = None,
30
+ ) -> Dict[str, Any]:
31
+ """Lists active programs configured in the clinic."""
32
+ params = {"limit": limit, "offset": offset}
33
+ if search is not None:
34
+ params["search"] = search
35
+ if programType is not None:
36
+ params["programType"] = programType
37
+ if facility_id is not None:
38
+ params["facility_id"] = facility_id
39
+ return self._client.get(self._base_path, params=params).json()
40
+
41
+ def get(self, id: str) -> Dict[str, Any]:
42
+ """Retrieves an active program by its ID."""
43
+ return self._client.get(f"{self._base_path}/{id}").json()
44
+
45
+ def create(self, payload: Dict[str, Any]) -> Dict[str, Any]:
46
+ """Creates a new program."""
47
+ return self._client.post(self._base_path, json=payload).json()
48
+
49
+ def update(self, id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
50
+ """Updates an active program's configurations by ID."""
51
+ return self._client.patch(f"{self._base_path}/{id}", json=payload).json()
@@ -0,0 +1,25 @@
1
+ """
2
+ Ritten SDK Resource Base Class.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ import inspect
9
+ from typing import Any
10
+
11
+ from ritten.decorators import exception_handler
12
+
13
+
14
+ class Resource:
15
+ """
16
+ A base class for all SDK resources.
17
+ It automatically wraps all public methods with an exception handler.
18
+ """
19
+
20
+ def __init_subclass__(cls, **kwargs: Any) -> None:
21
+ super().__init_subclass__(**kwargs)
22
+
23
+ for attr_name, attr_value in cls.__dict__.items():
24
+ if inspect.isfunction(attr_value) and not attr_name.startswith("_"):
25
+ setattr(cls, attr_name, exception_handler(attr_value))
@@ -0,0 +1,51 @@
1
+ """
2
+ Ritten SDK Users Resource.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ import httpx
9
+ from typing import Dict, Any
10
+
11
+ from ritten.resources.resource import Resource
12
+
13
+
14
+ class Users(Resource):
15
+ """
16
+ Handles all interactions with the Ritten API `/staff`, `/users`, and `/teams` endpoints.
17
+ """
18
+
19
+ def __init__(self, client: httpx.Client):
20
+ self._client = client
21
+ self._base_path = "/users"
22
+
23
+ def list(self) -> Dict[str, Any]:
24
+ """Lists users in a clinic."""
25
+ return self._client.get("staff").json()
26
+
27
+ def create(self, payload: Dict[str, Any]) -> Dict[str, Any]:
28
+ """Creates a new user and triggers an invitation email."""
29
+ return self._client.post(self._base_path, json=payload).json()
30
+
31
+ def delete(self, id: str) -> None:
32
+ """Deletes a user account."""
33
+ self._client.delete(f"{self._base_path}/{id}")
34
+
35
+ # --- Roles ---
36
+
37
+ def assign_role(self, user_id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
38
+ """Assigns a role to a user."""
39
+ return self._client.post(
40
+ f"{self._base_path}/{user_id}/roles", json=payload
41
+ ).json()
42
+
43
+ def remove_role(self, user_id: str, role_id: str) -> None:
44
+ """Removes a role from a user."""
45
+ self._client.delete(f"{self._base_path}/{user_id}/roles/{role_id}")
46
+
47
+ # --- Clinic Teams ---
48
+
49
+ def list_clinic_teams(self) -> Dict[str, Any]:
50
+ """Lists all clinic teams and their users."""
51
+ return self._client.get("teams").json()
ritten/ritten.py ADDED
@@ -0,0 +1,171 @@
1
+ """
2
+ Ritten SDK Client.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ from calendar import Calendar
9
+ from functools import cached_property
10
+
11
+ import httpx
12
+ from ritten.auth import Auth
13
+ from ritten.config import Config
14
+ from ritten.decorators import exception_handler
15
+ from ritten.exceptions import RittenClientError, RittenAPIError, ERROR_MAP
16
+ from ritten.resources import (
17
+ Calendar,
18
+ Cases,
19
+ Contacts,
20
+ Facilities,
21
+ Forms,
22
+ Insurance,
23
+ Organizations,
24
+ Patients,
25
+ Programs,
26
+ Users,
27
+ )
28
+ from ritten.storage import TokenStorage
29
+
30
+
31
+ class Ritten:
32
+ """A client for interacting with the Ritten API."""
33
+
34
+ @exception_handler
35
+ def __init__(
36
+ self,
37
+ tenant_id: str | None = None,
38
+ client_id: str | None = None,
39
+ client_secret: str | None = None,
40
+ storage: TokenStorage | None = None,
41
+ *,
42
+ config: Config | None = None,
43
+ ):
44
+ """Initialize the RittenClient with authentication and connection settings."""
45
+
46
+ self.config: Config
47
+ if config:
48
+ self.config = config
49
+ elif tenant_id and client_id and client_secret:
50
+ self.config = Config(
51
+ tenant_id=tenant_id,
52
+ client_id=client_id,
53
+ client_secret=client_secret,
54
+ storage=storage,
55
+ )
56
+ else:
57
+ raise RittenClientError(
58
+ "Either a Config object or tenant_id, client_id, and client_secret must be provided."
59
+ )
60
+
61
+ self.auth = Auth(self.config)
62
+
63
+ try:
64
+ self._build_http_client()
65
+ except Exception as e:
66
+ raise RittenClientError(
67
+ f"Failed to initialize HTTP client: {str(e)}."
68
+ ) from e
69
+
70
+ def _get_default_headers(self) -> dict:
71
+ """Generate default headers for API requests, including authentication."""
72
+
73
+ return {
74
+ "Content-Type": "application/json",
75
+ "X-Ritten-Tenant": self.config.tenant_id,
76
+ }
77
+
78
+ def _raise_on_error_hook(self, response: httpx.Response):
79
+ """Hook to raise exceptions on HTTP error responses."""
80
+
81
+ try:
82
+ response.raise_for_status()
83
+ except httpx.HTTPStatusError as e:
84
+ status_code = e.response.status_code
85
+
86
+ # Yield to the Auth class for expiration retries
87
+ if status_code == 401:
88
+ return
89
+
90
+ response.read()
91
+ error_message = f"Ritten API Error [{status_code}]: {e.response.text}"
92
+
93
+ # Raise specific exception or default to base
94
+ ExceptionClass = ERROR_MAP.get(status_code, RittenAPIError)
95
+ raise ExceptionClass(error_message, status_code) from e
96
+
97
+ def _build_http_client(self) -> None:
98
+ """Build an HTTP client with the specified configuration."""
99
+
100
+ # Configure limits explicitly based on user inputs
101
+ limits = httpx.Limits(
102
+ max_connections=self.config.max_connections,
103
+ max_keepalive_connections=self.config.max_keepalive_connections,
104
+ keepalive_expiry=self.config.keepalive_expiry,
105
+ )
106
+
107
+ self.client = httpx.Client(
108
+ base_url=self.config.base_url,
109
+ headers=self._get_default_headers(),
110
+ auth=self.auth,
111
+ limits=limits,
112
+ timeout=self.config.timeout,
113
+ event_hooks={"response": [self._raise_on_error_hook]},
114
+ )
115
+
116
+ @exception_handler
117
+ def close(self):
118
+ """Close the HTTP client and release resources."""
119
+ self.client.close()
120
+
121
+ # --- Resource Accessors ---
122
+
123
+ @cached_property
124
+ def calendar(self):
125
+ """Access the Calendar resource."""
126
+ return Calendar(self.client)
127
+
128
+ @cached_property
129
+ def cases(self):
130
+ """Access the Cases resource."""
131
+ return Cases(self.client)
132
+
133
+ @cached_property
134
+ def contacts(self):
135
+ """Access the Contacts resource."""
136
+ return Contacts(self.client)
137
+
138
+ @cached_property
139
+ def forms(self):
140
+ """Access the Forms resource."""
141
+ return Forms(self.client)
142
+
143
+ @cached_property
144
+ def facilities(self):
145
+ """Access the Facilities resource."""
146
+ return Facilities(self.client)
147
+
148
+ @cached_property
149
+ def insurance(self):
150
+ """Access the Insurance resource."""
151
+ return Insurance(self.client)
152
+
153
+ @cached_property
154
+ def organizations(self):
155
+ """Access the Organizations resource."""
156
+ return Organizations(self.client)
157
+
158
+ @cached_property
159
+ def patients(self):
160
+ """Access the Patients resource."""
161
+ return Patients(self.client)
162
+
163
+ @cached_property
164
+ def programs(self):
165
+ """Access the Programs resource."""
166
+ return Programs(self.client)
167
+
168
+ @cached_property
169
+ def users(self):
170
+ """Access the Users resource."""
171
+ return Users(self.client)
@@ -0,0 +1,7 @@
1
+ from .token_storage import TokenStorage
2
+ from .memory_storage import MemoryStorage
3
+
4
+ __all__ = [
5
+ "TokenStorage",
6
+ "MemoryStorage",
7
+ ]
@@ -0,0 +1,22 @@
1
+ """
2
+ In-memory token storage implementation.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+
9
+ class MemoryStorage:
10
+ """
11
+ In-memory token storage implementation.
12
+ This is a simple storage mechanism that keeps the token in memory.
13
+ """
14
+
15
+ def __init__(self, initial_token: str | None = None):
16
+ self._token = initial_token
17
+
18
+ def get_token(self) -> str | None:
19
+ return self._token
20
+
21
+ def set_token(self, token: str) -> None:
22
+ self._token = token
@@ -0,0 +1,25 @@
1
+ """
2
+ Ritten SDK Token Storage Protocol.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ from typing import Protocol, runtime_checkable
9
+
10
+
11
+ @runtime_checkable
12
+ class TokenStorage(Protocol):
13
+ """
14
+ Contract for token storage.
15
+
16
+ This allows for flexible implementations, such as in-memory, file-based, or database storage.
17
+ """
18
+
19
+ def get_token(self) -> str | None:
20
+ """Retrieve the current access token, if it exists."""
21
+ ...
22
+
23
+ def set_token(self, token: str) -> None:
24
+ """Store a new access token."""
25
+ ...
ritten/utils.py ADDED
@@ -0,0 +1,15 @@
1
+ """
2
+ Utility functions for the Ritten SDK.
3
+
4
+ :copyright: (c) 2026 by Wesley Gonçalves.
5
+ :license: MIT, see LICENSE for more details.
6
+ """
7
+
8
+ from datetime import datetime, timezone
9
+
10
+
11
+ def to_iso_format(dt: datetime) -> str:
12
+ """Converts a datetime object into a clean ISO 8601 string."""
13
+ if dt.tzinfo == timezone.utc:
14
+ return dt.isoformat(timespec="seconds").replace("+00:00", "Z")
15
+ return dt.isoformat(timespec="seconds")
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: ritten-python-sdk
3
+ Version: 1.0.0
4
+ Summary: Python SDK for connecting applications to the Ritten EMR Platform. Simplifies integration with the Behavioral Health Operations API.
5
+ License-File: LICENSE
6
+ Keywords: ritten,emr,healthcare,sdk,python
7
+ Author: Wesley Gonçalves
8
+ Author-email: dev@wesleygoncalves.com
9
+ Requires-Python: >=3.10
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Requires-Dist: httpx (>=0.28.1,<0.29.0)
17
+ Requires-Dist: pydantic (>=2.13.4,<3.0.0)
18
+ Project-URL: Documentation, https://github.com/wesleygoncalves/ritten-python-sdk/blob/main/README.md
19
+ Project-URL: Homepage, https://github.com/wesleygoncalves/ritten-python-sdk
20
+ Project-URL: changelog, https://github.com/wesleygoncalves/ritten-python-sdk/blob/main/CHANGELOG.md
21
+ Project-URL: issues, https://github.com/wesleygoncalves/ritten-python-sdk/issues
22
+ Project-URL: source, https://github.com/wesleygoncalves/ritten-python-sdk
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Ritten API Integration
26
+
27
+ Python SDK for connecting applications to the [Ritten EMR Platform](https://docs.ritten.io/). This library simplifies integration with Ritten's Behavioral Health Operations API, allowing developers to use Ritten API seamlessly from any Python environment.
28
+
29
+ Ritten API specifications:
30
+
31
+ - [Documentation](https://docs.ritten.io/)
32
+ - Version: 1
33
+
34
+ ## Installation
35
+
36
+ The SDK requires **Python 3.10 or higher**. Install it directly via `pip`:
37
+
38
+ ```bash
39
+ pip install ritten-python-sdk
40
+
41
+ # Using poetry
42
+ poetry add ritten-python-sdk
43
+
44
+ # Using pipenv
45
+ pipenv install ritten-python-sdk
46
+ ```
47
+
48
+ ## Quickstart Guide
49
+
50
+ To get started, you must first obtain your integrator `client_id` and `client_secret` from your Ritten administrator portal.
51
+
52
+ ---
53
+
54
+ ## Advanced Resources
55
+
56
+ - Review the official [Ritten API Documentation](https://docs.ritten.io/) for explicit payload schemas.
57
+ - Check the `/examples` directory inside this repository for production-ready boilerplate code.
58
+
59
+ ## About the Author
60
+
61
+ This SDK is developed and maintained by [Wesley Gonçalves](https://github.com/wesleygoncalves) under MIT license. Contributions and feedback are welcome!
62
+
@@ -0,0 +1,26 @@
1
+ ritten/__init__.py,sha256=cTgBgEimjNrXHPMdRwzYoGy2mbnbXLRyubNlb9iLDHA,1420
2
+ ritten/auth.py,sha256=TCCGngqqs77Zkzw8oQh3nTpncOspCGoedc-D78XEAJA,2896
3
+ ritten/config.py,sha256=T3ZirCVlHAowexHXLpBlFuyCcGDHejuNxkOEDBSIcrk,2408
4
+ ritten/decorators.py,sha256=5JhGtxuKGq1_0ZLHjQVe5qgb_DP_AiSfOC5QTi0oh5I,1236
5
+ ritten/exceptions.py,sha256=TnkBwrRnzxr4BsILpMHHjr6Ge2flMj8LoaYP9bqErWc,1854
6
+ ritten/resources/__init__.py,sha256=ZrmphNH4aLA2Q101QhVIWPvD6ocfFMRy1C7i1Z_RNOM,825
7
+ ritten/resources/calendar.py,sha256=-Ff1IlaY2Ex-xpCyM5Ev0WT_HX0R1ZQTcPJN_ptKYCo,921
8
+ ritten/resources/cases.py,sha256=-hM06JpXrbUgS_h1WF0C6erChktUI9DP0hotVimvQX4,1530
9
+ ritten/resources/contacts.py,sha256=rVYSTMjHqztxfNBC82-pmESXqgRM0VO8hzQl_9zco9Y,1732
10
+ ritten/resources/facilities.py,sha256=GcsoSn_oIas61a037hEZoN_Pl5WZ_YrTkFtNHLrcc5w,1784
11
+ ritten/resources/forms.py,sha256=XM2hmGcca1Bu0FIUKCXMu4Rn_yaLxbCzkuoPhEpEc5Y,951
12
+ ritten/resources/insurance.py,sha256=dRB-NWMcNZ8jBWGV1fkDMs2imbOANX5i9jxD7wcyDfA,783
13
+ ritten/resources/organizations.py,sha256=jWwWJWsrWx58uNCQatg2wUug6c2DE4htc3You3FRatA,2171
14
+ ritten/resources/patients.py,sha256=N6_7ABzEtBJWGfDKa2WYhb_zJm3jPgMUGBEMD2c_gyY,3832
15
+ ritten/resources/programs.py,sha256=rhWZ_JUw_AJgjYBIc0TPFMFqMZbTx3fXy4YkuNA58uI,1651
16
+ ritten/resources/resource.py,sha256=JaYSSjtvzdQ9MItAozdMBLc8DMxca9qnKyoFzK4EntI,676
17
+ ritten/resources/users.py,sha256=2nJHVgdxEb9oZCfRD3gUfeUNSrtydPnvLPvEZNWv_ao,1548
18
+ ritten/ritten.py,sha256=kdTBWwq9q-zr9_PK0RNWREJGgTg-JLVvle6ch2wJfsI,4880
19
+ ritten/storage/__init__.py,sha256=k-UrqZXOIkTvwkRlWTDNGzkZwqr1umoyoLH9A71sFIc,138
20
+ ritten/storage/memory_storage.py,sha256=74rdYQMNaFHevPz1c4BZoe2hyKbtlDmoWoHmbleDiSs,527
21
+ ritten/storage/token_storage.py,sha256=fEEt91rFeAnhRD5p7XUiSK5Fzm7UnGSD1MyEeVmugoQ,591
22
+ ritten/utils.py,sha256=nACKXwMCXweawRVd1zQuyq_X1kTFr863Gp2bNVKLm30,434
23
+ ritten_python_sdk-1.0.0.dist-info/METADATA,sha256=XoWZy3S8G0XcQ4FgwJgFrYHu08Q7Iw5CVckmTPHls0I,2365
24
+ ritten_python_sdk-1.0.0.dist-info/WHEEL,sha256=EGEvSphFYqXKs23-kQBeyNoJP1nrT8ZJKQoi5p5DYL8,88
25
+ ritten_python_sdk-1.0.0.dist-info/licenses/LICENSE,sha256=RDlmenqWEqYFQ0g09ctFA35mXr1uk_YyK4iLDp_mGeI,1074
26
+ ritten_python_sdk-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.4.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wesley Gonçalves
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.