machineconfig 6.36__py3-none-any.whl → 6.37__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.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

@@ -64,9 +64,9 @@ def get_app():
64
64
  nw_apps.command(name="i", help="Install SSH server", hidden=True)(install_ssh_server)
65
65
  nw_apps.command(name="add-ssh-key", help="🔑 [k] Add SSH public key to this machine", no_args_is_help=True)(add_ssh_key)
66
66
  nw_apps.command(name="k", help="Add SSH public key to this machine", hidden=True, no_args_is_help=True)(add_ssh_key)
67
- nw_apps.command(name="add-ssh-identity", help="🗝️ [a] Add SSH identity (private key) to this machine")(add_ssh_identity)
68
- nw_apps.command(name="a", help="Add SSH identity (private key) to this machine", hidden=True)(add_ssh_identity)
69
- nw_apps.command(name="show-address", help="[A] Show this computer addresses on network")(show_address)
67
+ nw_apps.command(name="add-ssh-identity", help="🗝️ [A] Add SSH identity (private key) to this machine")(add_ssh_identity)
68
+ nw_apps.command(name="A", help="Add SSH identity (private key) to this machine", hidden=True)(add_ssh_identity)
69
+ nw_apps.command(name="show-address", help="📌 [a] Show this computer addresses on network")(show_address)
70
70
  nw_apps.command(name="a", help="Show this computer addresses on network", hidden=True)(show_address)
71
71
  nw_apps.command(name="debug-ssh", help="🐛 [d] Debug SSH connection")(debug_ssh)
72
72
  nw_apps.command(name="d", help="Debug SSH connection", hidden=True)(debug_ssh)
@@ -1,4 +1,3 @@
1
-
2
1
  from pathlib import Path
3
2
  from typing import Callable, Optional, Union, Any, Protocol, List, TypeVar
4
3
  import logging
@@ -152,6 +151,64 @@ def to_pickle(obj: Any, path: Path) -> None:
152
151
  path.write_bytes(pickle.dumps(obj))
153
152
 
154
153
 
154
+ class CacheMemory[T]():
155
+ def __init__(
156
+ self, source_func: Callable[[], T], expire: timedelta, logger: LoggerTemplate, name: Optional[str] = None
157
+ ) -> None:
158
+ self.cache: T
159
+ self.source_func = source_func
160
+ self.time_produced = datetime.now()
161
+ self.logger = logger
162
+ self.expire = expire
163
+ self.name = name if isinstance(name, str) else str(self.source_func)
164
+ self.last_call_is_fresh = False
165
+
166
+ @property
167
+ def age(self) -> timedelta:
168
+ return datetime.now() - self.time_produced
169
+
170
+ def __call__(self, fresh: bool = False) -> T:
171
+ self.last_call_is_fresh = False
172
+ if fresh or not hasattr(self, "cache"):
173
+ if self.logger:
174
+ why = "There was an explicit fresh order." if fresh else "Previous cache never existed."
175
+ self.logger.warning(f"""
176
+ 🆕 ════════════════════ NEW CACHE ════════════════════
177
+ 🔄 {self.name} cache: Populating fresh cache from source func
178
+ ℹ️ Reason: {why}
179
+ ════════════════════════════════════════════════════════""")
180
+ self.cache = self.source_func()
181
+ self.last_call_is_fresh = True
182
+ self.time_produced = datetime.now()
183
+ else:
184
+ age = self.age
185
+ if age > self.expire:
186
+ if self.logger:
187
+ self.logger.warning(f"""
188
+ 🔄 ════════════════════ CACHE UPDATE ════════════════════
189
+ ⚠️ {self.name} cache: Updating cache from source func
190
+ ⏱️ Age = {age} > {self.expire}
191
+ ════════════════════════════════════════════════════════""")
192
+ self.cache = self.source_func()
193
+ self.last_call_is_fresh = True
194
+ self.time_produced = datetime.now()
195
+ else:
196
+ if self.logger:
197
+ self.logger.warning(f"""
198
+ ✅ ════════════════════ USING CACHE ════════════════════
199
+ 📦 {self.name} cache: Using cached values
200
+ ⏱️ Lag = {age}
201
+ ════════════════════════════════════════════════════════""")
202
+ return self.cache
203
+
204
+ @staticmethod
205
+ def as_decorator(expire: timedelta, logger: LoggerTemplate, name: Optional[str] = None):
206
+ def decorator(source_func: Callable[[], T2]) -> CacheMemory["T2"]:
207
+ res = CacheMemory(source_func=source_func, expire=expire, logger=logger, name=name)
208
+ return res
209
+ return decorator
210
+
211
+
155
212
  class Cache[T](): # This class helps to accelrate access to latest data coming from expensive function. The class has two flavours, memory-based and disk-based variants."""
156
213
  def __init__(
157
214
  self, source_func: Callable[[], T], expire: timedelta, logger: LoggerTemplate, path: Path, saver: Callable[[T, Path], Any] = to_pickle, reader: Callable[[Path], T] = from_pickle, name: Optional[str] = None
@@ -180,8 +237,7 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
180
237
  📦 ════════════════════ CACHE OPERATION ════════════════════
181
238
  🔄 {self.name} cache: Reading cached values from `{self.path}`
182
239
  ⏱️ Lag = {age}
183
- ════════════════════════════════════════════════════════════
184
- """
240
+ ════════════════════════════════════════════════════════════"""
185
241
  try:
186
242
  self.cache = self.reader(self.path)
187
243
  except Exception as ex:
@@ -190,8 +246,7 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
190
246
  ❌ ════════════════════ CACHE ERROR ════════════════════
191
247
  ⚠️ {self.name} cache: Cache file is corrupted
192
248
  🔍 Error: {ex}
193
- ════════════════════════════════════════════════════════
194
- """
249
+ ════════════════════════════════════════════════════════"""
195
250
  self.logger.warning(msg1 + msg2)
196
251
  self.cache = self.source_func()
197
252
  self.last_call_is_fresh = True
@@ -208,8 +263,7 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
208
263
  🆕 ════════════════════ NEW CACHE ════════════════════
209
264
  🔄 {self.name} cache: Populating fresh cache from source func
210
265
  ℹ️ Reason: {why}
211
- ════════════════════════════════════════════════════════
212
- """)
266
+ ════════════════════════════════════════════════════════""")
213
267
  self.cache = self.source_func() # fresh data.
214
268
  self.last_call_is_fresh = True
215
269
  self.time_produced = datetime.now()
@@ -248,21 +302,3 @@ class Cache[T](): # This class helps to accelrate access to latest data coming
248
302
  return res
249
303
 
250
304
  return decorator
251
-
252
- # def from_cloud(self, cloud: str, rel2home: bool = True, root: Optional[str] = None):
253
- # assert self.path is not None
254
- # exists = self.path.exists()
255
- # exists_but_old = exists and ((datetime.now() - datetime.fromtimestamp(self.path.stat().st_mtime)) > self.expire)
256
- # if not exists or exists_but_old:
257
- # returned_path = self.path.from_cloud(cloud=cloud, rel2home=rel2home, root=root)
258
- # if returned_path is None and not exists:
259
- # raise FileNotFoundError(f"❌ Failed to get @ {self.path}. Build the cache first with signed API.")
260
- # elif returned_path is None and exists:
261
- # self.logger.warning(f"""
262
- # ⚠️ ════════════════════ CLOUD FETCH WARNING ════════════════════
263
- # 🔄 Failed to get fresh data from cloud
264
- # 📦 Using old cache @ {self.path}
265
- # ════════════════════════════════════════════════════════════════""")
266
- # else:
267
- # pass # maybe we don't need to fetch it from cloud, if its too hot
268
- # return self.reader(self.path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 6.36
3
+ Version: 6.37
4
4
  Summary: Dotfiles management package
5
5
  Author-email: Alex Al-Saffar <programmer@usa.com>
6
6
  License: Apache 2.0
@@ -177,7 +177,7 @@ machineconfig/scripts/python/devops_helpers/__init__.py,sha256=47DEQpj8HBSa-_TIm
177
177
  machineconfig/scripts/python/devops_helpers/cli_config.py,sha256=B48SZzei0WG04GqvYfu3qyfcCIFqD3sfoXfcZJylYy4,5402
178
178
  machineconfig/scripts/python/devops_helpers/cli_config_dotfile.py,sha256=rjTys4FNf9_feP9flWM7Zvq17dxWmetSiGaHPxp25nk,2737
179
179
  machineconfig/scripts/python/devops_helpers/cli_data.py,sha256=2OWwp86-ncpGoSP9IblW7Jjej-wc-PuS8KRZ5xh0l1c,1774
180
- machineconfig/scripts/python/devops_helpers/cli_nw.py,sha256=nI_zmcmUvijVeXIWT2dN5onoy3ou-lub1cL-SJImmDA,4125
180
+ machineconfig/scripts/python/devops_helpers/cli_nw.py,sha256=1slGev50V3sHlVSt6mnFSV9faIzrnvtwXmJxnCnVJJ0,4131
181
181
  machineconfig/scripts/python/devops_helpers/cli_repos.py,sha256=Y5HgbNUyt7iehXyfmqPjVVjCsbZI-1Q6w1XwKQb_FkU,12331
182
182
  machineconfig/scripts/python/devops_helpers/cli_self.py,sha256=iMHmfK1uIXot9hbM44Ocy8jr5_QgayrO7SvQ8PMIL2E,5739
183
183
  machineconfig/scripts/python/devops_helpers/cli_share_server.py,sha256=q9pFJ6AxPuygMr3onMNOKEuuQHbVE_6Qoyo7xRT5FX0,4196
@@ -394,7 +394,7 @@ machineconfig/utils/options.py,sha256=vUO4Kej-vDOv64wHr2HNDyu6PATURpjd7xp6N8OOoJ
394
394
  machineconfig/utils/path_extended.py,sha256=WyJwoHnXdvSQQJ-yrxTX78FpqYmgVeKDYpNEB9UsRck,53223
395
395
  machineconfig/utils/path_helper.py,sha256=0e3Xh3BAEv27oqcezNeVLHJllGmLEgLH4T1l90m-650,8014
396
396
  machineconfig/utils/procs.py,sha256=rw8LR8MjGgvtrpcgxb3hudq2B9fkkpYUXe9x5-FgHuc,10694
397
- machineconfig/utils/scheduler.py,sha256=u56Y0UOIq-0WcwzScwjoiKFzBV47Lx--4lR52UD3y0M,14089
397
+ machineconfig/utils/scheduler.py,sha256=Uk6VT-gG7cOevnsKRcQPobTdr5zUZF0kLkdieByReMU,15749
398
398
  machineconfig/utils/scheduling.py,sha256=RF1iXJpqf4Dg18jdZWtBixz97KAHC6VKYqTFSpdLWuc,11188
399
399
  machineconfig/utils/source_of_truth.py,sha256=ZAnCRltiM07ig--P6g9_6nEAvNFC4X4ERFTVcvpIYsE,764
400
400
  machineconfig/utils/ssh.py,sha256=6Iy3Zlq3ByY_tafiVkRBLIB5Bi-5Eoyb675MsSP3xgw,39079
@@ -422,8 +422,8 @@ machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoS
422
422
  machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
423
423
  machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
424
424
  machineconfig/utils/ssh_utils/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
425
- machineconfig-6.36.dist-info/METADATA,sha256=JA8ifAAkirF9gk4UOYLZ9PEHu-Rczw1kv_5o58Q9AT8,2928
426
- machineconfig-6.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
427
- machineconfig-6.36.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
428
- machineconfig-6.36.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
429
- machineconfig-6.36.dist-info/RECORD,,
425
+ machineconfig-6.37.dist-info/METADATA,sha256=b51_ax1f6DD0BoSyi02WShSamZFEf47NEx7gBTD2YCg,2928
426
+ machineconfig-6.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
427
+ machineconfig-6.37.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
428
+ machineconfig-6.37.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
429
+ machineconfig-6.37.dist-info/RECORD,,