''' Created on 20 avr. 2022 @author: denis ''' import os import yaml import time import importlib from datetime import datetime import string, secrets import uuid from threading import Event, Thread from urllib.parse import urlsplit import asyncio import mmap import fcntl import psutil SHM_DIR = "/dev/shm" def open_shm(name: str, size: int, create=True): path = os.path.join(SHM_DIR, name) flags = os.O_RDWR | (os.O_CREAT if create else 0) fd = os.open(path, flags) try: if create: os.ftruncate(fd, size) mm = mmap.mmap(fd, size) finally: os.close(fd) return mm, path def read_shm(name: str, size: int): mm, path = open_shm(name, size, create=False) # @UnusedVariable try: mm.seek(0) data = mm.read(size) return data.rstrip(b"\0") finally: mm.close() def write_shm(name: str, size: int, data: bytes): mm, path = open_shm(name, size, create=True) fd = os.open(path, os.O_RDWR) try: fcntl.flock(fd, fcntl.LOCK_EX) try: mm.seek(0) mm.write(data.ljust(size, b"\0")[:size]) mm.flush() finally: fcntl.flock(fd, fcntl.LOCK_UN) finally: mm.close() os.close(fd) def get_tmpfs_info(mount_point="/ramdisk"): def sizeof(n): for unit in ['B','KB','MB','GB','TB']: if n < 1024: return f"{n:.1f}{unit}" n /= 1024 return f"{n:.1f}PB" usage = None for part in psutil.disk_partitions(all=True): if part.mountpoint == mount_point and part.fstype.lower() == "tmpfs": usage = psutil.disk_usage(part.mountpoint) print(f"Mount: {part.mountpoint}") print(f" Device: {part.device}") print(f" Fstype: {part.fstype}") print(f" Total: {usage.total} bytes ({sizeof(usage.total)})") print(f" Used: {usage.used} bytes ({sizeof(usage.used)})") print(f" Free: {usage.free} bytes ({sizeof(usage.free)})") print(f" Percent used: {usage.percent}%") break return { "percent": usage.percent, "mount": part.mountpoint, "device": part.device, "fstype": part.fstype, "total": usage.total, "used": usage.used, "free": usage.free, } def get_cpu_info(): # cpu percent par coeur et moyennes load return { "cpu_percent_per_cpu": psutil.cpu_percent(interval=0.5, percpu=True), "cpu_percent_total": psutil.cpu_percent(interval=None), "load_avg": os.getloadavg(), # (1,5,15) "cpu_count": psutil.cpu_count(logical=True), } def get_memory_info(): vm = psutil.virtual_memory() sm = psutil.swap_memory() return { "total": vm.total, "available": vm.available, "used": vm.used, "free": vm.free, "percent": vm.percent, "swap_total": sm.total, "swap_used": sm.used, "swap_free": sm.free, "swap_percent": sm.percent, } def get_disk_info(path="/"): du = psutil.disk_usage(path) return { "path": path, "total": du.total, "used": du.used, "free": du.free, "percent": du.percent, } def extract_host_port_path(url, default_port=None): """ Retoure (host, port, path) où: - host: string (IP ou hostname) ou None - port: int ou None (utilise default_port si fourni et aucun port explicite) - path: string (chemin + query + fragment si présents), ou '' si absent """ parts = urlsplit(url if '://' in url else '//' + url, scheme='') host = parts.hostname port = parts.port or default_port # Reconstruire path complet: path + ('?' + query) + ('#' + fragment) path = parts.path or '' if parts.query: path += '?' + parts.query if parts.fragment: path += '#' + parts.fragment return host, port, path def image_path(imagefile): image_path = imagefile.path pdir = os.path.dirname(image_path) os.makedirs(pdir, exist_ok=True) return str(image_path) def serialize_datetime(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError("Type not serializable") def start_async(): loop = asyncio.new_event_loop() Thread(target=loop.run_forever, daemon=True).start() return loop def stop_async(loop): loop.call_soon_threadsafe(loop.stop) def submit_async(loop, awaitable): return asyncio.run_coroutine_threadsafe(awaitable, loop) def to_choice(d): choices = [] for k, v in d.items(): choices.append((k, v)) return choices def get_instance_class(module): modulename, classname = module.rsplit(".", 1) return getattr(importlib.import_module(modulename), classname) def wait_for(timeout): Event().wait(timeout) def yaml_load(f): with open(f, 'r') as stream: return yaml.safe_load(stream) return {} def yaml_save(f, context): with open(f, 'w') as stream: yaml.dump(context, stream, default_flow_style = False) def get_uuid(): return str(hex(uuid.getnode()))[2:] def millis(): return round(time.time() * 1000) def now(): return datetime.now() def ts_now(): # float second return now().timestamp() def ts_now_s(): return int(ts_now()) def ts_now_ms(): return int(ts_now()*1000) def ts_now_us(): return int(ts_now()*1000000) def random_num(n=16): alphabet = string.digits return ''.join(secrets.choice(alphabet) for i in range(n)) # @UnusedVariable def random_chars(n=6): alphabet = string.ascii_letters + string.digits return ''.join(secrets.choice(alphabet) for i in range(n)) # @UnusedVariable def get_apikey(n=32): chars = 'abcdefgh01234ijklABCD4567EFGHIJKLmnopqrstuvwxyz0123456789MNOPQRS789TUVWXYZ' return ''.join(secrets.choice(chars) for i in range(n)) # @UnusedVariable def gen_keywords(s): c = s.replace(',', ' ').replace('+', ' ') return [ w.strip() for w in c.split(' ') if w] def gen_device_uuid(n=19): return hex(int(random_num(n)))[2:] def get_device_uuid(n=19): return f'0x{gen_device_uuid(n)}'