晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
| DIR:/opt/imunify360/venv/lib64/python3.11/site-packages/defence360agent/utils/ |
| Current File : //opt/imunify360/venv/lib64/python3.11/site-packages/defence360agent/utils/common.py |
import asyncio
import datetime
import functools
import logging
import socket
import time
import re
import os
import sys
MINUTE = datetime.timedelta(minutes=1).total_seconds()
HOUR = datetime.timedelta(hours=1).total_seconds()
DAY = datetime.timedelta(days=1).total_seconds()
WEEK = datetime.timedelta(weeks=1).total_seconds()
logger = logging.getLogger(__name__)
class ServiceBase(object):
"""Base service class."""
def __init__(self, loop):
self._loop = loop
self._should_stop = False
self._main_task = None
self._state = self.StoppedState(self)
def start(self):
return self._state.start()
def should_stop(self):
return self._state.should_stop()
async def wait(self):
return await self._state.wait()
def is_running(self):
return self._state.is_running()
async def _run(self):
raise NotImplementedError
class State(object):
def __init__(self, obj):
""":type obj: ServiceBase"""
self._obj = obj
def start(self):
pass
def should_stop(self):
pass
async def wait(self):
task = self._obj._main_task
if task:
await task
def is_running(self):
return False
class StoppedState(State):
def _on_stop(self, future):
self._obj._state = ServiceBase.StoppedState(self._obj)
self._obj._should_stop = False
def start(self):
obj = self._obj
obj._main_task = obj._loop.create_task(obj._run())
obj._main_task.add_done_callback(self._on_stop)
obj._state = ServiceBase.RunningState(obj)
class RunningState(State):
def should_stop(self):
obj = self._obj
obj._should_stop = True
obj._main_task.cancel()
obj._state = ServiceBase.StoppingState(obj)
def is_running(self):
return True
class StoppingState(State):
def start(self):
raise ProgrammingError(
"Cannot start stopping service. Please wait while it stop."
)
class ProgrammingError(Exception):
pass
class RateLimit:
"""Decorator to limit function calls to one per *period* seconds.
If less than *period* seconds have passed since the last call,
then the request to call the function is replace with an *on_drop*
call with the same arguments.
If *on_drop* is None [default] then the call is just dropped
"""
def __init__(self, period, timer=time.monotonic, *, on_drop=None):
self._next_call_time = None
self._period = period
self._timer = timer
self._on_drop = on_drop
@property
def should_be_called(self):
return (
self._next_call_time is None
or self._next_call_time <= self._timer()
)
def __call__(self, func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if self.should_be_called:
self._next_call_time = self._timer() + self._period
return func(*args, **kwargs)
elif self._on_drop is not None:
return self._on_drop(*args, **kwargs)
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
if self.should_be_called:
self._next_call_time = self._timer() + self._period
return await func(*args, **kwargs)
elif self._on_drop is not None:
return self._on_drop(*args, **kwargs)
return async_wrapper if asyncio.iscoroutinefunction(func) else wrapper
rate_limit = RateLimit
class CoalesceCalls:
def __init__(self):
self.call_time = float("-inf")
self.delayed_call = None
def coalesce_calls(self, period, *, done_callback=None):
"""
Decorator to coalesce coroutine calls to one per *period* seconds.
Requests for a coroutine call in a given time period are coalesced:
If t is the time of the last call, then N call requests in the [t,
t+period) time interval results in a single call at the
t+period time iff N>0 i.e.,
if less than *period* seconds have passed since the last call,
then the calls are coalesced: (N-1) requests are dropped, Nth
requests is performed in *period* seconds.
It is unspecified which exact call is made if arguments differ.
If the call is not dropped then *done_callback* is attached
to the task when the coroutine is scheduled with the event loop.
Given `c` is the time of the last [actual] call (`loop.create_task()`)
And `T` is the coalesce time period
When a call request arrives at `t` time
Then
| call pending? | t>c+T | c<=t<=c+T | t<c |
|----------------+--------------------------------+------------+------|
| no p. call | call soon | call at c+T| warn |
| p. call at c+T | cancel the call/warn, call soon| drop call | warn |
"""
def decorator(coro):
@functools.wraps(coro)
async def wrapper(*args, **kwargs):
loop = kwargs.get("loop")
if loop is None:
loop = asyncio.get_event_loop()
if args or kwargs:
args_repr = "*%r, **%r" % (args, kwargs)
else: # special case no args case
args_repr = ""
call_repr = "%s(%s)" % (coro.__name__, args_repr)
def log_exception(task):
"""Log task's error
if any with event's loop exception handler.
CancelledError is not logged.
"""
if not task.cancelled() and task.exception() is not None:
loop.call_exception_handler(
{
"message": "Unhandled exception during "
+ call_repr,
"exception": task.exception(),
"task": task,
}
)
def call_delayed(coro, args, kwargs):
"""Call & schedule the delayed coroutine now."""
logger.info("Schedule call %s", call_repr)
self.call_time = loop.time()
self.delayed_call = None
task = loop.create_task(coro(*args, **kwargs))
task.add_done_callback(
log_exception
if done_callback is None
else done_callback
)
now = loop.time()
if now > (self.call_time + period): # call immediately
if self.delayed_call is not None:
# get string representation for logs
# before cancelling the call
old_delayed_call_repr = str(self.delayed_call)
self.delayed_call.cancel()
self.delayed_call = None
logger.warning(
"There was a scheduled call (%s)"
" but more than period (%r) seconds passed"
" since the last call (%r, now=%r)",
old_delayed_call_repr,
period,
self.call_time,
now,
)
logger.info(
"Satisfy the call request soon: %s. No calls in"
" more than %r seconds since the start",
call_repr,
period,
)
self.delayed_call = loop.call_soon(
call_delayed, coro, args, kwargs
)
elif self.call_time <= now <= (self.call_time + period):
delay = (self.call_time + period) - now
if self.delayed_call is not None: # drop call request
logger.info(
"Drop call request for %s"
", enforcing one call per %r seconds limit"
". Next call is in ~%.2f seconds",
call_repr,
period,
delay,
)
else: # schedule call request
assert self.delayed_call is None
logger.info(
"Delay call request: %s for ~%.2f seconds"
". Enforcing one call per %r seconds limit",
call_repr,
delay,
period,
)
self.delayed_call = loop.call_at(
self.call_time + period,
call_delayed,
coro,
args,
kwargs,
)
else: # now < call_time
logger.warning(
"Drop call request for %s, reason: last call time"
" (%r, now=%r) is in the future",
call_repr,
self.call_time,
now,
)
return wrapper
return decorator
webserver_gracefull_restart = CoalesceCalls()
def get_hostname():
"""Returns readable name of the server.
It is sent to CLN and allows user to sort out his servers.
"""
hostname = socket.getfqdn()
if hostname is None or hostname.lower().startswith("localhost"):
return socket.gethostname()
return hostname
# Everything from there is copied from setuptools package
# Copied from setuptools/_distutils/version.py
class Version:
"""Abstract base class for version numbering classes. Just provides
constructor (__init__) and reproducer (__repr__), because those
seem to be the same for all version numbering classes; and route
rich comparisons to _cmp.
"""
def __init__(self, vstring=None):
if vstring:
self.parse(vstring)
def __repr__(self):
return "{} ('{}')".format(self.__class__.__name__, str(self))
def __eq__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c == 0
def __lt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c < 0
def __le__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c <= 0
def __gt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c > 0
def __ge__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c >= 0
# Copied from setuptools/_distutils/version.py
class LooseVersion(Version):
"""Version numbering for anarchists and software realists.
Implements the standard interface for version number classes as
described above. A version number consists of a series of numbers,
separated by either periods or strings of letters. When comparing
version numbers, the numeric components will be compared
numerically, and the alphabetic components lexically. The following
are all valid version numbers, in no particular order:
1.5.1
1.5.2b2
161
3.10a
8.02
3.4j
1996.07.12
3.2.pl0
3.1.1.6
2g6
11g
0.960923
2.2beta29
1.13++
5.5.kw
2.0b1pl0
In fact, there is no such thing as an invalid version number under
this scheme; the rules for comparison are simple and predictable,
but may not always give the results you want (for some definition
of "want").
"""
component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE)
def parse(self, vstring):
# I've given up on thinking I can reconstruct the version string
# from the parsed tuple -- so I just store the string here for
# use by __str__
self.vstring = vstring
components = [
x for x in self.component_re.split(vstring) if x and x != "."
]
for i, obj in enumerate(components):
try:
components[i] = int(obj)
except ValueError:
pass
self.version = components
def __str__(self):
return self.vstring
def __repr__(self):
return "LooseVersion ('%s')" % str(self)
def _cmp(self, other):
if isinstance(other, str):
other = LooseVersion(other)
elif not isinstance(other, LooseVersion):
return NotImplemented
if self.version == other.version:
return 0
if self.version < other.version:
return -1
if self.version > other.version:
return 1
# Copied from setuptools/_distutils/spawn.py
def find_executable(executable, path=None):
"""Tries to find 'executable' in the directories listed in 'path'.
A string listing directories separated by 'os.pathsep'; defaults to
os.environ['PATH']. Returns the complete filename or None if not found.
"""
_, ext = os.path.splitext(executable)
if (sys.platform == "win32") and (ext != ".exe"):
executable = executable + ".exe"
if os.path.isfile(executable):
return executable
if path is None:
path = os.environ.get("PATH", None)
if path is None:
try:
path = os.confstr("CS_PATH")
except (AttributeError, ValueError):
# os.confstr() or CS_PATH is not available
path = os.defpath
# bpo-35755: Don't use os.defpath if the PATH environment variable is
# set to an empty string
# PATH='' doesn't match, whereas PATH=':' looks in the current directory
if not path:
return None
paths = path.split(os.pathsep)
for p in paths:
f = os.path.join(p, executable)
if os.path.isfile(f):
# the file exists, we have a shot at spawn working
return f
return None
|