@@ -9,6 +9,11 @@ Rheel Data Management (RDM) provides a clean `.rdm` file format and
99Python API for structured, section-based data storage with enforced
1010types.
1111
12+ Since version 2.0 RDM features Rheel Temporary Data (RTD), which
13+ provides clean ` .rtd ` files for storing temporary data that expires
14+ at a given time. RTD is not section-based but features all other
15+ functions that RDM does.
16+
1217It is designed for developers who want more structure and type safety
1318than JSON or TOML --- without the complexity of a database.
1419
@@ -30,6 +35,12 @@ than JSON or TOML --- without the complexity of a database.
3035- Supports ` datetime ` , ` date ` , ` time ` , and ` Path ` natively
3136- Safe variable handling with deep copy
3237
38+ ** NEW in v2:**
39+ - Temporary data system with expiration support (.rtd)
40+ - Per-key TTL (time-to-live) expiration
41+ - Automatic expired key cleanup on save
42+ - Expiration extension and inspection API
43+
3344------------------------------------------------------------------------
3445
3546## 📦 Installation
@@ -49,28 +60,42 @@ import rheelDM
4960------------------------------------------------------------------------
5061
5162## 📄 Example ` .rdm ` File
52-
5363``` rdm
64+ # Rheel Data Management 2.0
65+
5466[user123]
5567name : str = "Steve"
5668score : int = 42
5769tags : list[str] = ["admin", "tester"]
5870prefs : dict[int,str] = {1: "dark", 2: "light"}
5971```
6072
73+ ## 📄 Example ` .rtd ` File
74+ ``` rtd
75+ # Rheel Temporary Data @ Rheel Data Management 2.0
76+
77+ [2026-03-04T18:14:37.891803+00:00]
78+ effect : str = "burning"
79+
80+ [2026-03-04T18:35:07.172342+00:00]
81+ premium_member : bool = True
82+ ```
83+
6184Clean. Typed. Readable.
6285
6386------------------------------------------------------------------------
6487
6588## 🚀 Basic Usage
6689
90+ For each heading there are 2 examples (when required). The first is RDM and the second is RTD
91+
6792### Create and Save
6893
6994``` python
7095import rheelDM
7196
7297data = rheelDM.Obj()
73- user = data.section(" user123" ) # for simplicity user always refers to this section
98+ user = data.section(" user123" ) # for simplicity user always refers to this section in RDM files
7499
75100user.set(" name" , str , " Steve" )
76101user.set(" score" , int , 42 )
@@ -79,6 +104,16 @@ user.set("prefs", dict[int, str], {1: "dark", 2: "light"})
79104
80105data.save(" botdata.rdm" )
81106```
107+ ``` python
108+ import rheelDM, datetime
109+
110+ temp = rheelDM.TempObj()
111+
112+ temp.set(" name" , str , " Steve" , ttl = 30 ) # Expires 30 seconds from now (also works with datetime.timedelta)
113+ temp.set(" score" , int , 42 , expires_at = datetime.datetime(2026 ,3 ,3 ,18 ,0 ,tzinfo = datetime.timezone.utc)) # Expires at given timestamp
114+
115+ temp.save(" tempbotdata.rtd" )
116+ ```
82117
83118### Load Data
84119
@@ -89,8 +124,7 @@ default_data = rheelDM.Obj()
89124default_data.section(" user123" ).set(" name" , str , " noName" )
90125default_data.section(" user123" ).set(" score" , int , 0 )
91126
92- default_items = rheelDM.Obj()
93- default_items.section(" user123" ).set(" items" , list , [1 ])
127+ default_items = rheelDM.Obj.load(" default_items.rdm" )
94128
95129loaded = rheelDM.Obj.load(" botdata.rdm" , default_data) # uses a copy of default if file not found (this can also be a boolean for catching missing files)
96130user = loaded.section(" user123" )
@@ -99,11 +133,21 @@ print(user.get("name")) # "Steve"
99133print (user.get(" score" )) # 42
100134print (user.get(" items" , default_items)) # [1] (uses a copy of default because "items" is not defined in botdata.rdm)
101135```
136+ ``` python
137+ default = rheel.TempObj.load(" default.rtd" )
138+
139+ loaded = rheel.TempObj.load(" tempbotdata.rtd" , default)
140+
141+ print (loaded.get(" score" )) # 42 or <ExpiredKey key="score" expired_at='2026-03-03T18:00:00.000000+00:00'>
142+ print (loaded.get(" name" , default)) # "Steve" or default
143+ print (loaded.get_expiration(" name" )) # timestamp of expiration
144+ ```
102145
103146### Modify Data
104147
105148#### Overwrite
106149``` python
150+ # same with RTD
107151user.set(" name" , str , " Alex" )
108152print (user.get(" name" )) # "Alex"
109153
@@ -113,6 +157,7 @@ print(user.get("name")) # "Alex"
113157```
114158#### Add or Multiply (` int ` , ` float ` , ` datetime ` )
115159``` python
160+ # same with RTD
116161from datetime import datetime
117162
118163user.set(" score" , int , 10 ) # 10
@@ -126,6 +171,7 @@ user.add("last_login", 3605) # 2026-02-21T22:39:23.398038
126171```
127172#### Extend (` str ` , ` list ` , ` set ` , ` dict ` , ` Path ` )
128173``` python
174+ # same with RTD
129175from pathlib import Path
130176
131177user.set(" name" , str , " Steve" ) # "Steve"
@@ -145,15 +191,22 @@ config_dir = Path("/settings")
145191user.set(" config_file" , Path, config_dir) # Path(/settings)
146192user.extend(" config_file" , " steve3828.rdm" ) # Path(/settings/steve3828.rdm)
147193```
194+ #### Extend Expiration:
195+ ``` python
196+ # not featured in RDM
197+ temp.extend_expiration(" name" , seconds = 30 ) # adds 30 seconds
198+ temp.extend_expiration(" name" , new_expires_at = datetime.datetime(2026 ,3 ,3 ,18 ,0 ,tzinfo = datetime.timezone.utc)) # set new expiration timestamp
199+ ```
148200#### Convert non-RDM Files
149201``` python
202+ # not featured in RTD
150203rheelDM.Obj.convert_file(" /settings/data.json" , overwrite = True )
151204rheelDM.Obj.load(" /settings/data.rdm" )
152205```
153206
154207### Delete Data
155208``` python
156- user.delete(" score" ) # key, value and type of "score" will be deleted entirely from the RDM file.
209+ user.delete(" score" ) # key, value and type of "score" will be deleted entirely from the RDM or RTD file.
157210```
158211
159212------------------------------------------------------------------------
@@ -179,20 +232,6 @@ user.delete("score") # key, value and type of "score" will be deleted entirely f
179232- pathlib:
180233 - ` Path `
181234
182- Example:
183-
184- ``` python
185- from datetime import datetime
186- from pathlib import Path
187-
188- user.set(" id" , int , 1234567890 )
189- user.set(" names" , dict[str , str ], {" username" : " steve3828" , " displayname" : " Steve" })
190- user.set(" last_login" , datetime, datetime.now())
191- user.set(" config_file" , Path, Path(" config/settings.txt" ))
192- ```
193-
194- ------------------------------------------------------------------------
195-
196235### Custom Type Registry
197236
198237You can register your own types globally.
@@ -215,6 +254,7 @@ rheelDM.TypeRegistry.register(
215254Now you can use it like any native type:
216255
217256``` python
257+ # same with TempObj and set()
218258data.section(" settings" ).set(" theme" , Color, Color(" #ff8800" ))
219259```
220260
@@ -249,7 +289,7 @@ RDM can store all of these, even the most complex and custom types.
249289
250290### Cleaner Structure
251291
252- Section-based and auto-aligned format keeps large files organized and readable.
292+ Section-based (not RTD) and auto-aligned format keeps large files organized and readable.
253293
254294### Human Editable
255295
0 commit comments