mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-14 03:17:05 +00:00
m1n1.utils.Reloadable: Only reload each module once
This avoids confusion with types changing ID when the same module is repeatedly reloaded. Now we use the file mtime and only reload things which have changed since last time, and dependent modules. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
ba478f2de5
commit
a714c74e1a
1 changed files with 24 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import bisect, copy, heapq, importlib, sys, itertools
|
import bisect, copy, heapq, importlib, sys, itertools, time, os
|
||||||
from construct import Adapter, Int64ul, Int32ul, Int16ul, Int8ul
|
from construct import Adapter, Int64ul, Int32ul, Int16ul, Int8ul
|
||||||
|
|
||||||
__all__ = []
|
__all__ = []
|
||||||
|
@ -53,24 +53,40 @@ def chexdump32(s, st=0, abbreviate=True):
|
||||||
last = val
|
last = val
|
||||||
skip = False
|
skip = False
|
||||||
|
|
||||||
class Reloadable:
|
class ReloadableMeta(type):
|
||||||
|
def __new__(cls, name, bases, dct):
|
||||||
|
m = super().__new__(cls, name, bases, dct)
|
||||||
|
m._load_time = time.time()
|
||||||
|
return m
|
||||||
|
|
||||||
|
class Reloadable(metaclass=ReloadableMeta):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _reloadcls(cls):
|
def _reloadcls(cls):
|
||||||
mods = []
|
mods = []
|
||||||
for c in cls.mro():
|
for c in cls.mro():
|
||||||
mods.append(sys.modules[c.__module__])
|
mod = sys.modules[c.__module__]
|
||||||
|
cur_cls = getattr(mod, c.__name__)
|
||||||
|
mods.append((cur_cls, mod))
|
||||||
if c.__name__ == "Reloadable":
|
if c.__name__ == "Reloadable":
|
||||||
break
|
break
|
||||||
|
|
||||||
for mod in mods[::-1]:
|
reloaded = set()
|
||||||
mod = importlib.reload(mod)
|
newest = 0
|
||||||
|
for pcls, mod in mods[::-1]:
|
||||||
|
source = getattr(mod, "__file__", None)
|
||||||
|
if not source:
|
||||||
|
continue
|
||||||
|
newest = max(newest, os.stat(source).st_mtime, pcls._load_time)
|
||||||
|
if (reloaded or pcls._load_time < newest) and mod.__name__ not in reloaded:
|
||||||
|
mod = importlib.reload(mod)
|
||||||
|
reloaded.add(mod.__name__)
|
||||||
|
|
||||||
return getattr(mod, cls.__name__)
|
return getattr(mods[0][1], cls.__name__)
|
||||||
|
|
||||||
def _reloadme(self):
|
def _reloadme(self):
|
||||||
self.__class__ = self._reloadcls()
|
self.__class__ = self._reloadcls()
|
||||||
|
|
||||||
class RegisterMeta(type):
|
class RegisterMeta(ReloadableMeta):
|
||||||
def __new__(cls, name, bases, dct):
|
def __new__(cls, name, bases, dct):
|
||||||
m = super().__new__(cls, name, bases, dct)
|
m = super().__new__(cls, name, bases, dct)
|
||||||
|
|
||||||
|
@ -546,7 +562,7 @@ class NdRange:
|
||||||
iters = (i[j] for i, j in zip(self.ranges, item))
|
iters = (i[j] for i, j in zip(self.ranges, item))
|
||||||
return map(sum, itertools.product(*(([i] if isinstance(i, int) else i) for i in iters)))
|
return map(sum, itertools.product(*(([i] if isinstance(i, int) else i) for i in iters)))
|
||||||
|
|
||||||
class RegMapMeta(type):
|
class RegMapMeta(ReloadableMeta):
|
||||||
def __new__(cls, name, bases, dct):
|
def __new__(cls, name, bases, dct):
|
||||||
m = super().__new__(cls, name, bases, dct)
|
m = super().__new__(cls, name, bases, dct)
|
||||||
m._addrmap = {}
|
m._addrmap = {}
|
||||||
|
|
Loading…
Reference in a new issue