rtbnext 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,40 @@
1
+ """
2
+ Mover
3
+
4
+ Declares movers as the largest gains and losses over predefined time periods.
5
+ """
6
+
7
+ from typing import TypedDict
8
+
9
+ from rtbnext.schema.assets import ChangeItem
10
+ from rtbnext.schema.generic import MetaData
11
+
12
+ MoverItem = TypedDict( "MoverItem", {
13
+ "uri": str,
14
+ "name": str,
15
+ "value": float
16
+ } )
17
+
18
+ MoverEntry = TypedDict( "MoverEntry", {
19
+ "winner": list[ MoverItem ],
20
+ "loser": list[ MoverItem ]
21
+ } )
22
+
23
+ MoverBucket = TypedDict( "MoverBucket", {
24
+ "total": ChangeItem,
25
+ "networth": MoverEntry,
26
+ "percent": MoverEntry
27
+ } )
28
+
29
+ MoverData = TypedDict( "MoverData", {
30
+ "date": str,
31
+ "today": MoverBucket,
32
+ "ytd": MoverBucket
33
+ } )
34
+
35
+ Mover = TypedDict( "Mover", {
36
+ "$metadata": MetaData,
37
+ "date": str,
38
+ "today": MoverBucket,
39
+ "ytd": MoverBucket
40
+ } )
@@ -0,0 +1,137 @@
1
+ """
2
+ Profile
3
+
4
+ Declares profile records representing individuals, including personal
5
+ information, financial data, relationships, media, and historical statistics.
6
+ """
7
+
8
+ from typing import Literal, NotRequired, TypedDict
9
+
10
+ from rtbnext.schema.assets import Annual, Asset, Performance, Ranking, Realtime
11
+ from rtbnext.schema.generic import (
12
+ Education, Gender, Image, Industry, Location, MaritalStatus, MetaData, Organization,
13
+ ProfileStatusFlag, Relation, SelfMade, SelfMadeRank, Wiki
14
+ )
15
+
16
+ ProfileIndexItem = TypedDict( "ProfileIndexItem", {
17
+ "uri": str,
18
+ "name": str,
19
+ "text": str,
20
+ "aliases": list[ str ],
21
+ "desc": NotRequired[ str ],
22
+ "image": NotRequired[ str ]
23
+ } )
24
+
25
+ ProfileIndex = TypedDict( "ProfileIndex", {
26
+ "$metadata": MetaData,
27
+ "count": int,
28
+ "items": list[ ProfileIndexItem ]
29
+ } )
30
+
31
+ SearchIndexItem = TypedDict( "SearchIndexItem", {
32
+ "id": str,
33
+ "uri": str,
34
+ "deceased": bool,
35
+ "family": bool,
36
+ "dropOff": bool,
37
+ "embargo": bool,
38
+ "searchName": str,
39
+ "fullName": str,
40
+ "lastName": str,
41
+ "gender": NotRequired[ Gender ],
42
+ "birthDate": NotRequired[ str ],
43
+ "age": NotRequired[ int ],
44
+ "birthCountry": NotRequired[ str ],
45
+ "residenceCountry": NotRequired[ str ],
46
+ "citizenship": NotRequired[ str ],
47
+ "industry": NotRequired[ Industry ],
48
+ "source": NotRequired[ list[ str ] ],
49
+ "networth": NotRequired[ float ],
50
+ "rank": NotRequired[ int ],
51
+ "organization": NotRequired[ str ],
52
+ "maritalStatus": NotRequired[ MaritalStatus ],
53
+ "children": NotRequired[ int ],
54
+ "philanthropyScore": NotRequired[ int ],
55
+ "selfMade": NotRequired[ bool ],
56
+ "selfMadeRank": NotRequired[ SelfMadeRank ],
57
+ "wikidata": NotRequired[ str ],
58
+ "status": NotRequired[ ProfileStatusFlag ],
59
+ "score": NotRequired[ float ],
60
+ "timestamp": str
61
+ } )
62
+
63
+ SearchIndex = TypedDict( "SearchIndex", {
64
+ "$metadata": MetaData,
65
+ "count": int,
66
+ "items": list[ SearchIndexItem ]
67
+ } )
68
+
69
+ ProfileStatus = TypedDict( "ProfileStatus", {
70
+ "status": ProfileStatusFlag,
71
+ "score": float,
72
+ "flags": NotRequired[ list[ str ] ]
73
+ } )
74
+
75
+ ProfileMeta = TypedDict( "ProfileMeta", {
76
+ "schemaVersion": Literal[ "2" ],
77
+ "generator": str,
78
+ "lastModified": str,
79
+ "lastLookup": NotRequired[ str ],
80
+ "status": NotRequired[ ProfileStatus ]
81
+ } )
82
+
83
+ type ProfileHistoryItem = tuple[ str, int, float, float, float ]
84
+ type ProfileHistory = list[ ProfileHistoryItem ]
85
+
86
+ ProfileFlags = TypedDict( "ProfileFlags", {
87
+ "deceased": NotRequired[ bool ],
88
+ "family": NotRequired[ bool ],
89
+ "dropOff": NotRequired[ bool ],
90
+ "embargo": NotRequired[ bool ]
91
+ } )
92
+
93
+ ProfileName = TypedDict( "ProfileName", {
94
+ "fullName": str,
95
+ "shortName": str,
96
+ "lastName": str,
97
+ "firstName": str
98
+ } )
99
+
100
+ ProfileInfo = TypedDict( "ProfileInfo", {
101
+ "flags": ProfileFlags,
102
+ "name": ProfileName,
103
+ "gender": Gender,
104
+ "birthDate": NotRequired[ str ],
105
+ "birthPlace": NotRequired[ Location ],
106
+ "citizenship": NotRequired[ str ],
107
+ "residence": NotRequired[ Location ],
108
+ "maritalStatus": NotRequired[ MaritalStatus ],
109
+ "children": NotRequired[ int ],
110
+ "education": NotRequired[ list[ Education ] ],
111
+ "industry": Industry,
112
+ "source": list[ str ],
113
+ "selfMade": NotRequired[ SelfMade ],
114
+ "philanthropyScore": NotRequired[ int ],
115
+ "organization": NotRequired[ Organization ]
116
+ } )
117
+
118
+ ProfileBio = TypedDict( "ProfileBio", {
119
+ "cv": list[ str ],
120
+ "quotes": list[ str ],
121
+ "facts": list[ str ]
122
+ } )
123
+
124
+ ProfileData = TypedDict( "ProfileData", {
125
+ "id": str,
126
+ "uri": str,
127
+ "info": ProfileInfo,
128
+ "bio": ProfileBio,
129
+ "related": list[ Relation ],
130
+ "media": list[ Image ],
131
+ "realtime": NotRequired[ Realtime ],
132
+ "performance": NotRequired[ Performance ],
133
+ "ranking": list[ Ranking ],
134
+ "annual": list[ Annual ],
135
+ "assets": list[ Asset ],
136
+ "wiki": NotRequired[ Wiki ]
137
+ } )
@@ -0,0 +1,133 @@
1
+ """
2
+ Stats
3
+
4
+ Declares statistical data, grouped statistics, historical trends,
5
+ demographic distributions, and wealth analysis.
6
+ """
7
+
8
+ from typing import NotRequired, TypedDict
9
+
10
+ from rtbnext.schema.assets import ChangeItem
11
+ from rtbnext.schema.generic import (
12
+ AgeGroup, ChangeFlag, ChildrenGroup, Gender, Industry, MaritalStatus, MetaData, Percentile,
13
+ SelfMadeRank, WealthSpread
14
+ )
15
+
16
+ StatsData = TypedDict( "StatsData", {
17
+ "profiles": int,
18
+ "days": int
19
+ } )
20
+
21
+ GlobalStats = TypedDict( "GlobalStats", {
22
+ "$metadata": MetaData,
23
+ "stats": StatsData,
24
+ "date": str,
25
+ "count": int,
26
+ "total": float,
27
+ "woman": int,
28
+ "quota": float,
29
+ "today": NotRequired[ ChangeItem ],
30
+ "ytd": NotRequired[ ChangeItem ]
31
+ } )
32
+
33
+ DBStats = TypedDict( "DBStats", {
34
+ "$metadata": MetaData,
35
+ "files": int,
36
+ "size": int
37
+ } )
38
+
39
+ type HistoryItem = tuple[ str, int, float, int, float, float, float ]
40
+ type History = list[ HistoryItem ]
41
+
42
+ AgePyramidGroup = TypedDict( "AgePyramidGroup", {
43
+ "count": int,
44
+ "decades": dict[ AgeGroup, int ],
45
+ "max": int,
46
+ "min": int,
47
+ "mean": int
48
+ } )
49
+
50
+ ChildrenStats = TypedDict( "ChildrenStats", {
51
+ "full": dict[ str, int ],
52
+ "short": dict[ ChildrenGroup, int ]
53
+ } )
54
+
55
+ ProfileStats = TypedDict( "ProfileStats", {
56
+ "$metadata": MetaData,
57
+ "gender": dict[ Gender, int ],
58
+ "maritalStatus": dict[ MaritalStatus, int ],
59
+ "agePyramid": dict[ Gender, AgePyramidGroup ],
60
+ "children": ChildrenStats,
61
+ "selfMade": dict[ SelfMadeRank, int ],
62
+ "philanthropyScore": dict[ str, int ]
63
+ } )
64
+
65
+ ScatterItem = TypedDict( "ScatterItem", {
66
+ "uri": str,
67
+ "name": str,
68
+ "gender": Gender,
69
+ "age": int,
70
+ "networth": float
71
+ } )
72
+
73
+ Scatter = TypedDict( "Scatter", {
74
+ "$metadata": MetaData,
75
+ "count": int,
76
+ "items": list[ ScatterItem ]
77
+ } )
78
+
79
+ WealthStats = TypedDict( "WealthStats", {
80
+ "$metadata": MetaData,
81
+ "decades": dict[ AgeGroup, float ],
82
+ "gender": dict[ Gender, float ],
83
+ "percentiles": dict[ Percentile, float ],
84
+ "quartiles": tuple[ float, float, float ],
85
+ "spread": dict[ WealthSpread, float ],
86
+ "total": float,
87
+ "max": float,
88
+ "min": float,
89
+ "mean": float,
90
+ "median": float,
91
+ "stdDev": float
92
+ } )
93
+
94
+ Top10Item = TypedDict( "Top10Item", {
95
+ "uri": str,
96
+ "name": str,
97
+ "rank": int,
98
+ "networth": float,
99
+ "flag": ChangeFlag
100
+ } )
101
+
102
+ Top10 = TypedDict( "Top10", {
103
+ "$metadata": MetaData,
104
+ "entries": dict[ str, list[ Top10Item ] ]
105
+ } )
106
+
107
+ StatsIndexFirst = TypedDict( "StatsIndexFirst", {
108
+ "uri": str,
109
+ "name": str,
110
+ "rank": int,
111
+ "networth": float
112
+ } )
113
+
114
+ StatsIndexItem = TypedDict( "StatsIndexItem", {
115
+ "date": str,
116
+ "count": int,
117
+ "total": float,
118
+ "woman": int,
119
+ "quota": float,
120
+ "today": NotRequired[ ChangeItem ],
121
+ "ytd": NotRequired[ ChangeItem ],
122
+ "first": StatsIndexFirst
123
+ } )
124
+
125
+ IndustryStatsIndex = TypedDict( "IndustryStatsIndex", {
126
+ "$metadata": MetaData,
127
+ "items": dict[ Industry, StatsIndexItem ]
128
+ } )
129
+
130
+ CitizenshipStatsIndex = TypedDict( "CitizenshipStatsIndex", {
131
+ "$metadata": MetaData,
132
+ "items": dict[ str, StatsIndexItem ]
133
+ } )
@@ -0,0 +1,15 @@
1
+ """
2
+ System
3
+
4
+ Declares the system status endpoint type.
5
+ """
6
+
7
+ from typing import TypedDict
8
+
9
+ from rtbnext.schema.generic import MetaData, Service, StatusFlag
10
+
11
+ SystemStatus = TypedDict( "SystemStatus", {
12
+ "$metadata": MetaData,
13
+ "status": StatusFlag,
14
+ "services": dict[ Service, StatusFlag ]
15
+ } )
rtbnext/utils.py ADDED
@@ -0,0 +1,36 @@
1
+ """
2
+ Utils
3
+
4
+ Implements internal used utility methods.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from datetime import datetime, timezone
11
+
12
+
13
+ def sanitize( value: object, delimiter: str = "-" ) -> str:
14
+ """Sanitize a value for use as a normalized identifier."""
15
+
16
+ result = str( value ).strip().lower()
17
+ result = re.sub( r"[^a-z0-9]+", delimiter, result )
18
+ result = re.sub( rf"[{ re.escape( delimiter ) }]{{2,}}", delimiter, result )
19
+
20
+ return result
21
+
22
+
23
+ def ymd( value: object ) -> str:
24
+ """Convert a value to a UTC date string `YYYY-MM-DD`."""
25
+
26
+ text = str( value )
27
+
28
+ try:
29
+ dt = datetime.fromisoformat( text.replace( "Z", "+00:00" ) )
30
+ except ValueError:
31
+ dt = datetime.strptime( text, "%Y-%m-%d" )
32
+
33
+ if not dt.tzinfo:
34
+ dt = dt.replace( tzinfo= timezone.utc )
35
+
36
+ return dt.astimezone( timezone.utc ).strftime( "%Y-%m-%d" )
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: rtbnext
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the RTBNext API.
5
+ Project-URL: Homepage, https://rtbnext.de
6
+ Project-URL: Documentation, https://sdk.rtbnext.de
7
+ Project-URL: Repository, https://github.com/rtbnext/sdk-python
8
+ Project-URL: Bug Tracker, https://github.com/rtbnext/sdk-python/issues
9
+ Author-email: "Paul Köhler (komed3)" <webmaster@komed3.de>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api,billionaires,rtbnext,sdk
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: httpx>=0.28
25
+ Provides-Extra: dev
26
+ Requires-Dist: build>=1.5; extra == 'dev'
27
+ Requires-Dist: hatchling>=1.27; extra == 'dev'
28
+ Requires-Dist: isort>=8.0; extra == 'dev'
29
+ Requires-Dist: pre-commit>=4.6; extra == 'dev'
30
+ Requires-Dist: pylint>=4.0; extra == 'dev'
31
+ Requires-Dist: twine>=7.0; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # rtbnext
35
+
36
+ **Official Python SDK for the RTBNext API.**
37
+
38
+ The RTBNext SDK provides a typed, asynchronous interface for accessing billionaire profiles, lists, filters, statistics, historical data and system information from the [RTBNext API](https://api.rtbnext.de).
39
+
40
+ The SDK follows a consistent resource-oriented design: resources are loaded lazily, cached according to the configured cache mode, and expose typed helper methods for collections, time series and indexed data.
41
+
42
+ The package includes Python type information and is compatible with static type checkers such as Pyright, Pylance and mypy.
43
+
44
+ To find a list of all available API endpoints, please refer to the [API Documentation](https://docs.rtbnext.de). Also visit the [API endpoint](https://api.rtbnext.de) or review the [SDK Documentation](https://sdk.rtbnext.de) for additional details. For updates on current issues or maintenance, please refer to the [System Status](https://status.rtbnext.de).
45
+
46
+ ## Installation
47
+
48
+ Install the package using pip:
49
+
50
+ ```bash
51
+ pip install rtbnext
52
+ ```
53
+
54
+ ## First usage
55
+
56
+ Every client application **must identify** itself when creating an SDK instance. This information is sent with API requests and helps to provide transparency about API consumers.
57
+
58
+ ```py
59
+ import asyncio
60
+
61
+ from rtbnext import ClientIdentity, rtbnext
62
+
63
+
64
+ async def main() -> None:
65
+ async with rtbnext(
66
+ client= ClientIdentity(
67
+ name= "my-application",
68
+ version= "1.0.0",
69
+ contact= "https://example.com/contact"
70
+ )
71
+ ) as client:
72
+
73
+ stats = await client.stats.global_.data()
74
+ print( stats["count"] )
75
+
76
+
77
+ asyncio.run( main() )
78
+ ```
79
+
80
+ The client identity consists of:
81
+
82
+ - `name` — application or project name
83
+ - `version` — application version
84
+ - `contact` — optional contact URL
85
+ - `email` — optional contact email address
86
+
87
+ ## Core concepts
88
+
89
+ ### Lazy resources
90
+
91
+ Resources are not downloaded when they are created. Data is loaded only when it is requested.
92
+
93
+ ```py
94
+ profile = client.profile.get( "bill-gates" )
95
+
96
+ # No request has been made yet.
97
+
98
+ data = await profile.meta.data()
99
+ ```
100
+
101
+ ### Collections
102
+
103
+ Collection resources provide filtering, searching, sorting and paging helpers.
104
+
105
+ ```py
106
+ profiles = await client.profile.index.collection()
107
+
108
+ for profile in profiles.search( "bill" ).order_by( "networth", descending= True ).take( 5 ):
109
+ print( item.raw["name"], item.raw["uri"] )
110
+ ```
111
+
112
+ ### Time series
113
+
114
+ Historical data can be accessed through typed time-series resources.
115
+
116
+ ```py
117
+ history = await client.profile.get( "bill-gates" ).history.series()
118
+ print( history.latest )
119
+ ```
120
+
121
+ Time series collections support date-based navigation and cursor operations:
122
+
123
+ ```py
124
+ history.seek( "2026-01-01" )
125
+
126
+ while ( point := history.next ) is not None:
127
+ print( point["date"], point["networth"] )
128
+ ```
129
+
130
+ ## Cache behavior
131
+
132
+ The SDK includes a configurable resource cache layer that follows HTTP cache semantics. Resources are cached according to the selected cache mode and server-provided cache headers.
133
+
134
+ Supported cache modes:
135
+
136
+ - `ttl` — uses the server-defined cache lifetime (`Cache-Control`)
137
+ - `revalidate` — performs conditional requests using validators such as `ETag` and `Last-Modified`
138
+ - `session` — keeps resources during the lifetime of the SDK instance
139
+
140
+ The SDK does not bypass HTTP cache validation. Expired resources are refreshed according to the configured mode to prevent serving outdated data indefinitely.
141
+
142
+ A custom cache implementation can be provided by implementing the `Cache` protocol. This allows applications to integrate their own storage solutions, such as databases, filesystem caches or distributed cache systems.
143
+
144
+ The cache interface requires the following operations:
145
+
146
+ - retrieve a cached resource state
147
+ - store a resource state
148
+ - delete a resource
149
+ - clear the cache
150
+ - report the current cache size
151
+
152
+ ## Requirements
153
+
154
+ - Python 3.12+
155
+ - httpx 0.28+
156
+
157
+ ## License
158
+
159
+ **Copyright © 2026 RTBNext**
160
+ Created and maintained by [Paul Köhler](https://komed3.de) (komed3).
161
+ Licensed under the [MIT License](./LICENSE).
@@ -0,0 +1,36 @@
1
+ rtbnext/__init__.py,sha256=TNXYvCobmVdPAdJbEv7sg7s4F634z_SQi6vXPsAnBp8,685
2
+ rtbnext/_version.py,sha256=KNcBstbtD78JJl8q3nWrUj9jMVJzkBzbN6TgtGK0Krs,88
3
+ rtbnext/defaults.py,sha256=FNGTfDoqszDhtHqKVNJe3992Kx-LjYZry_-K1IUL_w0,586
4
+ rtbnext/rtbnext.py,sha256=iKuTE0YRK04ss_l7toT-P_XocddBW6lDXGdJmEZsOvI,3370
5
+ rtbnext/utils.py,sha256=1QQ0riYcRU34AuppLVsHdVgqulG0GxSTR_pL6UwyoaU,914
6
+ rtbnext/core/cache.py,sha256=mNjGnRuY8l2BSEGL9ELFwMxuf_58u0egKB0Oser0fa4,2749
7
+ rtbnext/core/http_client.py,sha256=SVMjujU4DsR8lx2CkK26L2FxFkM79yBxb9FIZe3o7ok,4740
8
+ rtbnext/core/loader.py,sha256=Qtp3I-cu0eiNZH3XGIYWYemCsFHkn-D4l53WPuruMKA,5891
9
+ rtbnext/core/parser.py,sha256=Q2eqCJSkvtf3MOet-k829Oowvq5YtCNSmq5T4aBsL6E,2501
10
+ rtbnext/core/rate_limiter.py,sha256=CIc-HRb9FxWE32R68CI8dI3yahD1iFp4oQM33VyXE-w,2536
11
+ rtbnext/endpoint/base.py,sha256=cWyVRxjGKwzxYpQjTbjODkGrN-0aCevTlocX30l6NBk,2676
12
+ rtbnext/endpoint/filter.py,sha256=hqdU3qg-VoA946NWhgOTI2htUJB_PwrQ531JMT22jwo,4132
13
+ rtbnext/endpoint/list.py,sha256=QrI9ImPqwyiiGszikTHSY09O9PhMYg5GaeevvH2W5dU,2714
14
+ rtbnext/endpoint/mover.py,sha256=Rd2CQCZT8LcUvp_yB7ITYVvtGE8Ey1BkNn3hFkhne-4,992
15
+ rtbnext/endpoint/profile.py,sha256=eBM5PgpLjQVwxOtkp7jbshzOAnZHALH31nSbPYYKJyE,5135
16
+ rtbnext/endpoint/stats.py,sha256=Of67GFCS9Ko16GgsCQOvyhmq5y_s0yGs-4aet1zzPQs,5129
17
+ rtbnext/endpoint/system.py,sha256=WnFr_MQcGIPpPYisj5GR9HxmPnnIeVvqlPnLQsWixnc,610
18
+ rtbnext/resource/base.py,sha256=bKLu-zcyWmKBnS7fMbEEg2S0ArvbdYuSVLxtEn1JUo4,6321
19
+ rtbnext/resource/collectable.py,sha256=PQExoPRXVxHhIs4FqWIBKVxqxQPfKj6fRV6YCSq9lak,6697
20
+ rtbnext/resource/collection.py,sha256=VF8F4_gmAg0s1B6jn8ozqhxCOW992dZMvbQhb8hNqUg,9404
21
+ rtbnext/resource/dateable.py,sha256=yk8Wh6G6MEuknnO3DLHnUWB3MCc1ahwMSQxFzQRbT_M,1932
22
+ rtbnext/resource/indexable.py,sha256=u7SUQn2FbSv60fuNYhp-NU62WhJkFAbXnlR9wtnkzC0,2872
23
+ rtbnext/resource/series.py,sha256=etCJL0h-A320LIBErdcHVQ5TON6oLDMfVY876etrnsU,8563
24
+ rtbnext/schema/assets.py,sha256=bcyGYut2waodFmG96nwJQU1w_Khe16N9VJDz58Fax9M,2439
25
+ rtbnext/schema/filter.py,sha256=ERXruDd5zr0vPx4lcMHzcF6cszz3kYJ4i9fEoWmEA1Y,790
26
+ rtbnext/schema/generic.py,sha256=y9rV3OnkPD7kkHGl2LeN1To8ajB0_xIG7ERVEsf3A3U,3149
27
+ rtbnext/schema/list.py,sha256=8AFcjmIVoAKOJir8OoTeMQuGS6Roi8vRbGWpyO5WWZs,1586
28
+ rtbnext/schema/mover.py,sha256=qwi17KqFxst5S429THM5hyPNm0qsr6g_QU2myxqNupc,820
29
+ rtbnext/schema/profile.py,sha256=O-lwGCRBjjHaUXzCjfP1167lJUhJQ7e0SahqO_G_Q4U,4019
30
+ rtbnext/schema/stats.py,sha256=6EdtHzTfycbhAniKm6O4bj5-nnm47sRoQ7fHcH1-Ipg,3234
31
+ rtbnext/schema/system.py,sha256=3k7mXHLWGJZbdwO5XUbNwedmq6ORiBSrmaOaQmwpnpw,315
32
+ rtbnext/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ rtbnext-1.0.0.dist-info/METADATA,sha256=tkofrQnAZgnxCd7l09HGVN6am33543MnklSgxYDvIpM,5369
34
+ rtbnext-1.0.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
35
+ rtbnext-1.0.0.dist-info/licenses/LICENSE,sha256=SifktjgxUZpaTEt1-2sH2TWqRQk0n0ZJST47kDI6oAU,1110
36
+ rtbnext-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RTBNext by Paul Köhler (komed3)
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.