OXIESEC PANEL
- Current Dir:
/
/
opt
/
alt
/
python37
/
lib
/
python3.7
/
site-packages
Server IP: 2a02:4780:11:1084:0:327f:3464:10
Upload:
Create Dir:
Name
Size
Modified
Perms
📁
..
-
04/17/2024 05:35:58 PM
rwxr-xr-x
📁
Babel-2.9.1-py3.7.egg-info
-
02/16/2024 08:52:02 PM
rwxr-xr-x
📁
Deprecated-1.2.13.dist-info
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
Jinja2-3.0.3-py3.7.egg-info
-
02/16/2024 08:52:04 PM
rwxr-xr-x
📁
Mako-1.1.0-py3.7.egg-info
-
02/16/2024 08:51:43 PM
rwxr-xr-x
📁
PyJWT-2.1.0-py3.7.egg-info
-
02/16/2024 08:51:56 PM
rwxr-xr-x
📁
PyMySQL-1.0.2.dist-info
-
03/16/2023 12:56:42 PM
rwxr-xr-x
📄
PySocks-1.5.7-py3.7.egg-info
322 bytes
11/14/2023 02:03:31 PM
rw-r--r--
📁
__pycache__
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
_distutils_hack
-
02/16/2024 08:49:51 PM
rwxr-xr-x
📁
aiosignal
-
02/16/2024 08:51:49 PM
rwxr-xr-x
📁
aiosignal-1.2.0a0-py3.7.egg-info
-
02/16/2024 08:51:49 PM
rwxr-xr-x
📁
alembic
-
02/16/2024 09:01:44 PM
rwxr-xr-x
📁
alembic-0.8.3-py3.7.egg-info
-
02/16/2024 09:01:44 PM
rwxr-xr-x
📁
async_timeout
-
02/16/2024 08:51:49 PM
rwxr-xr-x
📁
async_timeout-4.0.2-py3.7.egg-info
-
02/16/2024 08:51:49 PM
rwxr-xr-x
📁
asynctest
-
03/16/2023 12:57:44 PM
rwxr-xr-x
📁
asynctest-0.13.0.dist-info
-
03/16/2023 12:57:44 PM
rwxr-xr-x
📁
attr
-
02/16/2024 08:51:35 PM
rwxr-xr-x
📁
attrs-21.2.0-py3.7.egg-info
-
02/16/2024 08:51:35 PM
rwxr-xr-x
📁
babel
-
02/16/2024 08:52:02 PM
rwxr-xr-x
📁
beautifulsoup4-4.5.1-py3.7.egg-info
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
boto3
-
03/16/2023 12:57:26 PM
rwxr-xr-x
📁
boto3-1.26.92.dist-info
-
03/16/2023 12:57:26 PM
rwxr-xr-x
📁
botocore
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
botocore-1.29.92.dist-info
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
bs4
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
certifi
-
02/16/2024 08:51:36 PM
rwxr-xr-x
📁
certifi-2018.4.16-py3.7.egg-info
-
02/16/2024 08:51:36 PM
rwxr-xr-x
📁
chardet
-
02/16/2024 08:51:50 PM
rwxr-xr-x
📁
chardet-3.0.4-py3.7.egg-info
-
02/16/2024 08:51:50 PM
rwxr-xr-x
📁
charset_normalizer
-
02/16/2024 08:51:51 PM
rwxr-xr-x
📁
charset_normalizer-2.0.12-py3.7.egg-info
-
02/16/2024 08:51:51 PM
rwxr-xr-x
📁
cl_dom_collector
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clcommon
-
07/09/2024 11:23:41 AM
rwxr-xr-x
📁
clconfig
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clconfigure
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
cldashboard
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clevents
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
click
-
03/16/2023 12:56:53 PM
rwxr-xr-x
📁
click-8.1.3.dist-info
-
03/16/2023 12:56:53 PM
rwxr-xr-x
📁
cllimits_validator
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
cllimitslib_v2
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clquota
-
02/16/2024 09:04:47 PM
rwxr-xr-x
📁
clselect
-
02/16/2024 09:04:47 PM
rwxr-xr-x
📁
clselector
-
02/16/2024 09:04:47 PM
rwxr-xr-x
📁
clsentry
-
07/09/2024 11:23:41 AM
rwxr-xr-x
📁
clsummary
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clveconfig
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
clwizard
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
cssselect
-
03/16/2023 11:25:56 AM
rwxr-xr-x
📁
cssselect-0.9.2-py3.7.egg-info
-
03/16/2023 11:25:56 AM
rwxr-xr-x
📁
dateutil
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
decorator-5.1.1.dist-info
-
03/16/2023 12:57:03 PM
rwxr-xr-x
📄
decorator.py
16.36 KB
03/16/2023 12:57:03 PM
rw-r--r--
📁
deprecated
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
distlib
-
02/16/2024 09:01:49 PM
rwxr-xr-x
📄
distlib-0.3.4-py3.7.egg-info
1.13 KB
11/14/2023 12:11:47 PM
rw-r--r--
📄
distutils-precedence.pth
152 bytes
11/13/2023 09:35:13 PM
rw-r--r--
📁
docopt-0.6.2-py3.7.egg-info
-
02/16/2024 08:51:52 PM
rwxr-xr-x
📄
docopt.py
19.48 KB
06/16/2014 11:14:32 AM
rw-r--r--
📁
dquota
-
03/16/2023 12:56:36 PM
rwxr-xr-x
📁
dquota-0.4-py3.7.egg-info
-
03/16/2023 12:56:36 PM
rwxr-xr-x
📄
easy_install.py
126 bytes
03/16/2023 12:55:47 PM
rw-r--r--
📄
editor.py
2.5 KB
12/10/2019 05:53:59 PM
rwxr-xr-x
📁
elastic_transport
-
03/16/2023 12:55:59 PM
rwxr-xr-x
📁
elastic_transport-8.4.0.dist-info
-
03/16/2023 12:55:59 PM
rwxr-xr-x
📁
elasticsearch
-
03/16/2023 12:55:59 PM
rwxr-xr-x
📁
elasticsearch-8.6.2.dist-info
-
03/16/2023 12:55:59 PM
rwxr-xr-x
📁
exabgp
-
03/16/2023 12:55:54 PM
rwxr-xr-x
📁
exabgp-4.2.13-py3.7.egg-info
-
03/16/2023 12:55:54 PM
rwxr-xr-x
📁
filelock
-
02/16/2024 09:01:50 PM
rwxr-xr-x
📁
filelock-0.0.0-py3.7.egg-info
-
02/16/2024 09:01:50 PM
rwxr-xr-x
📁
fluent
-
03/16/2023 12:56:05 PM
rwxr-xr-x
📁
fluent_logger-0.10.0.dist-info
-
03/16/2023 12:56:05 PM
rwxr-xr-x
📁
future
-
02/16/2024 08:51:37 PM
rwxr-xr-x
📁
future-0.17.0-py3.7.egg-info
-
02/16/2024 08:51:37 PM
rwxr-xr-x
📁
graypy
-
03/16/2023 12:57:55 PM
rwxr-xr-x
📁
graypy-2.1.0.dist-info
-
03/16/2023 12:57:55 PM
rwxr-xr-x
📁
html5lib
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
html5lib-1.0.1-py3.7.egg-info
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
idna
-
02/16/2024 08:51:39 PM
rwxr-xr-x
📁
idna-2.5-py3.7.egg-info
-
02/16/2024 08:51:39 PM
rwxr-xr-x
📁
importlib_metadata
-
02/16/2024 08:52:09 PM
rwxr-xr-x
📁
importlib_metadata-0.0.0-py3.7.egg-info
-
02/16/2024 08:52:09 PM
rwxr-xr-x
📁
importlib_metadata-6.0.0.dist-info
-
03/16/2023 12:56:36 PM
rwxr-xr-x
📁
jinja2
-
02/16/2024 08:52:04 PM
rwxr-xr-x
📁
jmespath
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
jmespath-1.0.1.dist-info
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
jsons
-
03/16/2023 12:57:19 PM
rwxr-xr-x
📁
jsons-1.6.3.dist-info
-
03/16/2023 12:57:19 PM
rwxr-xr-x
📁
jsonschema
-
02/16/2024 08:52:09 PM
rwxr-xr-x
📁
jsonschema-3.2.0-py3.7.egg-info
-
02/16/2024 08:52:09 PM
rwxr-xr-x
📁
jwt
-
02/16/2024 09:05:10 PM
rwxr-xr-x
📁
libfuturize
-
02/16/2024 08:51:37 PM
rwxr-xr-x
📁
libpasteurize
-
02/16/2024 08:51:37 PM
rwxr-xr-x
📁
loguru
-
03/16/2023 12:57:30 PM
rwxr-xr-x
📁
loguru-0.6.0.dist-info
-
03/16/2023 12:57:30 PM
rwxr-xr-x
📁
lve_utils
-
09/05/2025 09:36:16 AM
rwxr-xr-x
📁
lvemanager
-
02/16/2024 09:04:47 PM
rwxr-xr-x
📁
lvestats
-
02/16/2024 09:04:54 PM
rwxr-xr-x
📁
mako
-
02/16/2024 08:51:43 PM
rwxr-xr-x
📁
nose
-
02/16/2024 08:51:55 PM
rwxr-xr-x
📁
nose-1.3.7-py3.7.egg-info
-
02/16/2024 08:51:55 PM
rwxr-xr-x
📁
packaging
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
packaging-23.0.dist-info
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
past
-
02/16/2024 08:51:37 PM
rwxr-xr-x
📁
pika
-
03/16/2023 12:56:36 PM
rwxr-xr-x
📁
pika-1.3.1.dist-info
-
03/16/2023 12:56:36 PM
rwxr-xr-x
📁
pip
-
02/16/2024 09:01:52 PM
rwxr-xr-x
📁
pip-20.2.4.dist-info
-
02/16/2024 09:01:52 PM
rwxr-xr-x
📁
pip-23.0.1.dist-info
-
03/16/2023 12:55:41 PM
rwxr-xr-x
📁
pkg_resources
-
02/16/2024 08:49:51 PM
rwxr-xr-x
📁
platformdirs
-
02/16/2024 09:01:54 PM
rwxr-xr-x
📁
platformdirs-0.0.0-py3.7.egg-info
-
02/16/2024 09:01:54 PM
rwxr-xr-x
📁
pr2modules
-
03/16/2023 12:56:30 PM
rwxr-xr-x
📁
prettytable-0.7.2-py3.7.egg-info
-
02/16/2024 09:01:54 PM
rwxr-xr-x
📄
prettytable.py
52.93 KB
04/06/2013 11:44:06 PM
rw-r--r--
📁
prometheus_client
-
03/16/2023 12:56:10 PM
rwxr-xr-x
📁
prometheus_client-0.16.0.dist-info
-
03/16/2023 12:56:10 PM
rwxr-xr-x
📁
pydig
-
03/16/2023 12:57:08 PM
rwxr-xr-x
📁
pydig-0.4.0.dist-info
-
03/16/2023 12:57:08 PM
rwxr-xr-x
📁
pymysql
-
03/16/2023 12:56:42 PM
rwxr-xr-x
📁
pyparsing
-
02/16/2024 08:51:57 PM
rwxr-xr-x
📁
pyparsing-3.0.9.dist-info
-
02/16/2024 08:51:57 PM
rwxr-xr-x
📁
pyroute2
-
03/16/2023 12:56:30 PM
rwxr-xr-x
📁
pyroute2-0.7.5.dist-info
-
03/16/2023 12:56:30 PM
rwxr-xr-x
📁
python_dateutil-2.8.2.dist-info
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
python_editor-0.4-py3.7.egg-info
-
02/16/2024 08:51:53 PM
rwxr-xr-x
📁
pytz
-
02/16/2024 08:52:01 PM
rwxr-xr-x
📁
pytz-2017.2-py3.7.egg-info
-
02/16/2024 08:52:01 PM
rwxr-xr-x
📁
raven
-
02/16/2024 08:51:42 PM
rwxr-xr-x
📁
raven-6.3.0-py3.7.egg-info
-
02/16/2024 08:51:42 PM
rwxr-xr-x
📁
redis
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
redis-4.1.4.dist-info
-
03/16/2023 12:57:13 PM
rwxr-xr-x
📁
requests
-
02/16/2024 08:51:59 PM
rwxr-xr-x
📁
requests-2.25.1.dist-info
-
03/16/2023 12:56:14 PM
rwxr-xr-x
📁
requests-2.26.0-py3.7.egg-info
-
02/16/2024 08:51:59 PM
rwxr-xr-x
📁
s3transfer
-
03/16/2023 12:57:25 PM
rwxr-xr-x
📁
s3transfer-0.6.0.dist-info
-
03/16/2023 12:57:26 PM
rwxr-xr-x
📁
schema-0.7.1-py3.7.egg-info
-
02/16/2024 08:52:05 PM
rwxr-xr-x
📄
schema.py
28.51 KB
09/09/2019 05:39:33 PM
rw-r--r--
📁
sentry_sdk
-
02/16/2024 09:01:45 PM
rwxr-xr-x
📁
sentry_sdk-1.3.1-py3.7.egg-info
-
02/16/2024 09:01:45 PM
rwxr-xr-x
📁
setuptools
-
02/16/2024 08:49:51 PM
rwxr-xr-x
📁
setuptools-44.1.0.dist-info
-
03/16/2023 12:55:48 PM
rwxr-xr-x
📁
setuptools-58.3.0.dist-info
-
02/16/2024 08:49:51 PM
rwxr-xr-x
📁
sh-1.14.3-py3.7.egg-info
-
03/16/2023 12:56:48 PM
rwxr-xr-x
📄
sh.py
127.79 KB
07/18/2022 06:46:38 AM
rw-r--r--
📁
six-1.15.0-py3.7.egg-info
-
02/16/2024 08:51:33 PM
rwxr-xr-x
📄
six.py
33.36 KB
05/21/2020 03:25:33 PM
rw-r--r--
📄
socks.py
29.25 KB
05/21/2016 09:54:42 PM
rw-r--r--
📄
sockshandler.py
2.84 KB
05/21/2016 09:54:42 PM
rw-r--r--
📁
ssa
-
02/16/2024 09:04:49 PM
rwxr-xr-x
📁
svgwrite
-
02/16/2024 09:01:46 PM
rwxr-xr-x
📁
svgwrite-1.3.0-py3.7.egg-info
-
02/16/2024 09:01:46 PM
rwxr-xr-x
📁
tabulate
-
03/16/2023 12:56:58 PM
rwxr-xr-x
📁
tabulate-0.9.0.dist-info
-
03/16/2023 12:56:58 PM
rwxr-xr-x
📁
tests
-
03/16/2023 12:57:55 PM
rwxr-xr-x
📁
typer
-
03/16/2023 12:56:53 PM
rwxr-xr-x
📁
typer-0.7.0.dist-info
-
03/16/2023 12:56:53 PM
rwxr-xr-x
📁
typing_extensions-3.7.4.3-py3.7.egg-info
-
02/16/2024 08:51:34 PM
rwxr-xr-x
📄
typing_extensions.py
81.76 KB
07/07/2020 10:29:25 PM
rw-r--r--
📁
typish
-
03/16/2023 12:57:19 PM
rwxr-xr-x
📁
typish-1.9.3.dist-info
-
03/16/2023 12:57:19 PM
rwxr-xr-x
📁
urllib3
-
02/16/2024 08:51:58 PM
rwxr-xr-x
📁
urllib3-1.26.6-py3.7.egg-info
-
02/16/2024 08:51:58 PM
rwxr-xr-x
📁
validators
-
03/16/2023 12:57:03 PM
rwxr-xr-x
📁
validators-0.20.0-py3.7.egg-info
-
03/16/2023 12:57:03 PM
rwxr-xr-x
📁
vendors_api
-
07/09/2024 11:23:41 AM
rwxr-xr-x
📁
virtualenv
-
03/16/2023 11:25:58 AM
rwxr-xr-x
📁
virtualenv-20.13.0-py3.7.egg-info
-
03/16/2023 11:25:58 AM
rwxr-xr-x
📁
webencodings
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
webencodings-0.5.1-py3.7.egg-info
-
03/16/2023 11:26:01 AM
rwxr-xr-x
📁
xray
-
02/16/2024 09:04:44 PM
rwxr-xr-x
📁
zipp
-
03/16/2023 12:56:30 PM
rwxr-xr-x
📁
zipp-0.0.0-py3.7.egg-info
-
02/16/2024 08:52:09 PM
rwxr-xr-x
📁
zipp-3.15.0.dist-info
-
03/16/2023 12:56:30 PM
rwxr-xr-x
📄
zipp.py
8.23 KB
12/31/2021 12:01:49 AM
rw-r--r--
Editing: decorator.py
Close
# ######################### LICENSE ############################ # # Copyright (c) 2005-2021, Michele Simionato # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # Redistributions in bytecode form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. """ Decorator module, see https://github.com/micheles/decorator/blob/master/docs/documentation.md for the documentation. """ import re import sys import inspect import operator import itertools from contextlib import _GeneratorContextManager from inspect import getfullargspec, iscoroutinefunction, isgeneratorfunction __version__ = '5.1.1' DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(') POS = inspect.Parameter.POSITIONAL_OR_KEYWORD EMPTY = inspect.Parameter.empty # this is not used anymore in the core, but kept for backward compatibility class FunctionMaker(object): """ An object with the ability to create functions with a given signature. It has attributes name, doc, module, signature, defaults, dict and methods update and make. """ # Atomic get-and-increment provided by the GIL _compile_count = itertools.count() # make pylint happy args = varargs = varkw = defaults = kwonlyargs = kwonlydefaults = () def __init__(self, func=None, name=None, signature=None, defaults=None, doc=None, module=None, funcdict=None): self.shortsignature = signature if func: # func can be a class or a callable, but not an instance method self.name = func.__name__ if self.name == '<lambda>': # small hack for lambda functions self.name = '_lambda_' self.doc = func.__doc__ self.module = func.__module__ if inspect.isroutine(func): argspec = getfullargspec(func) self.annotations = getattr(func, '__annotations__', {}) for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs', 'kwonlydefaults'): setattr(self, a, getattr(argspec, a)) for i, arg in enumerate(self.args): setattr(self, 'arg%d' % i, arg) allargs = list(self.args) allshortargs = list(self.args) if self.varargs: allargs.append('*' + self.varargs) allshortargs.append('*' + self.varargs) elif self.kwonlyargs: allargs.append('*') # single star syntax for a in self.kwonlyargs: allargs.append('%s=None' % a) allshortargs.append('%s=%s' % (a, a)) if self.varkw: allargs.append('**' + self.varkw) allshortargs.append('**' + self.varkw) self.signature = ', '.join(allargs) self.shortsignature = ', '.join(allshortargs) self.dict = func.__dict__.copy() # func=None happens when decorating a caller if name: self.name = name if signature is not None: self.signature = signature if defaults: self.defaults = defaults if doc: self.doc = doc if module: self.module = module if funcdict: self.dict = funcdict # check existence required attributes assert hasattr(self, 'name') if not hasattr(self, 'signature'): raise TypeError('You are decorating a non function: %s' % func) def update(self, func, **kw): """ Update the signature of func with the data in self """ func.__name__ = self.name func.__doc__ = getattr(self, 'doc', None) func.__dict__ = getattr(self, 'dict', {}) func.__defaults__ = self.defaults func.__kwdefaults__ = self.kwonlydefaults or None func.__annotations__ = getattr(self, 'annotations', None) try: frame = sys._getframe(3) except AttributeError: # for IronPython and similar implementations callermodule = '?' else: callermodule = frame.f_globals.get('__name__', '?') func.__module__ = getattr(self, 'module', callermodule) func.__dict__.update(kw) def make(self, src_templ, evaldict=None, addsource=False, **attrs): """ Make a new function from a given template and update the signature """ src = src_templ % vars(self) # expand name and signature evaldict = evaldict or {} mo = DEF.search(src) if mo is None: raise SyntaxError('not a valid function template\n%s' % src) name = mo.group(1) # extract the function name names = set([name] + [arg.strip(' *') for arg in self.shortsignature.split(',')]) for n in names: if n in ('_func_', '_call_'): raise NameError('%s is overridden in\n%s' % (n, src)) if not src.endswith('\n'): # add a newline for old Pythons src += '\n' # Ensure each generated function has a unique filename for profilers # (such as cProfile) that depend on the tuple of (<filename>, # <definition line>, <function name>) being unique. filename = '<decorator-gen-%d>' % next(self._compile_count) try: code = compile(src, filename, 'single') exec(code, evaldict) except Exception: print('Error in generated code:', file=sys.stderr) print(src, file=sys.stderr) raise func = evaldict[name] if addsource: attrs['__source__'] = src self.update(func, **attrs) return func @classmethod def create(cls, obj, body, evaldict, defaults=None, doc=None, module=None, addsource=True, **attrs): """ Create a function from the strings name, signature and body. evaldict is the evaluation dictionary. If addsource is true an attribute __source__ is added to the result. The attributes attrs are added, if any. """ if isinstance(obj, str): # "name(signature)" name, rest = obj.strip().split('(', 1) signature = rest[:-1] # strip a right parens func = None else: # a function name = None signature = None func = obj self = cls(func, name, signature, defaults, doc, module) ibody = '\n'.join(' ' + line for line in body.splitlines()) caller = evaldict.get('_call_') # when called from `decorate` if caller and iscoroutinefunction(caller): body = ('async def %(name)s(%(signature)s):\n' + ibody).replace( 'return', 'return await') else: body = 'def %(name)s(%(signature)s):\n' + ibody return self.make(body, evaldict, addsource, **attrs) def fix(args, kwargs, sig): """ Fix args and kwargs to be consistent with the signature """ ba = sig.bind(*args, **kwargs) ba.apply_defaults() # needed for test_dan_schult return ba.args, ba.kwargs def decorate(func, caller, extras=(), kwsyntax=False): """ Decorates a function/generator/coroutine using a caller. If kwsyntax is True calling the decorated functions with keyword syntax will pass the named arguments inside the ``kw`` dictionary, even if such argument are positional, similarly to what functools.wraps does. By default kwsyntax is False and the the arguments are untouched. """ sig = inspect.signature(func) if iscoroutinefunction(caller): async def fun(*args, **kw): if not kwsyntax: args, kw = fix(args, kw, sig) return await caller(func, *(extras + args), **kw) elif isgeneratorfunction(caller): def fun(*args, **kw): if not kwsyntax: args, kw = fix(args, kw, sig) for res in caller(func, *(extras + args), **kw): yield res else: def fun(*args, **kw): if not kwsyntax: args, kw = fix(args, kw, sig) return caller(func, *(extras + args), **kw) fun.__name__ = func.__name__ fun.__doc__ = func.__doc__ fun.__wrapped__ = func fun.__signature__ = sig fun.__qualname__ = func.__qualname__ # builtin functions like defaultdict.__setitem__ lack many attributes try: fun.__defaults__ = func.__defaults__ except AttributeError: pass try: fun.__kwdefaults__ = func.__kwdefaults__ except AttributeError: pass try: fun.__annotations__ = func.__annotations__ except AttributeError: pass try: fun.__module__ = func.__module__ except AttributeError: pass try: fun.__dict__.update(func.__dict__) except AttributeError: pass return fun def decoratorx(caller): """ A version of "decorator" implemented via "exec" and not via the Signature object. Use this if you are want to preserve the `.__code__` object properties (https://github.com/micheles/decorator/issues/129). """ def dec(func): return FunctionMaker.create( func, "return _call_(_func_, %(shortsignature)s)", dict(_call_=caller, _func_=func), __wrapped__=func, __qualname__=func.__qualname__) return dec def decorator(caller, _func=None, kwsyntax=False): """ decorator(caller) converts a caller function into a decorator """ if _func is not None: # return a decorated function # this is obsolete behavior; you should use decorate instead return decorate(_func, caller, (), kwsyntax) # else return a decorator function sig = inspect.signature(caller) dec_params = [p for p in sig.parameters.values() if p.kind is POS] def dec(func=None, *args, **kw): na = len(args) + 1 extras = args + tuple(kw.get(p.name, p.default) for p in dec_params[na:] if p.default is not EMPTY) if func is None: return lambda func: decorate(func, caller, extras, kwsyntax) else: return decorate(func, caller, extras, kwsyntax) dec.__signature__ = sig.replace(parameters=dec_params) dec.__name__ = caller.__name__ dec.__doc__ = caller.__doc__ dec.__wrapped__ = caller dec.__qualname__ = caller.__qualname__ dec.__kwdefaults__ = getattr(caller, '__kwdefaults__', None) dec.__dict__.update(caller.__dict__) return dec # ####################### contextmanager ####################### # class ContextManager(_GeneratorContextManager): def __init__(self, g, *a, **k): _GeneratorContextManager.__init__(self, g, a, k) def __call__(self, func): def caller(f, *a, **k): with self.__class__(self.func, *self.args, **self.kwds): return f(*a, **k) return decorate(func, caller) _contextmanager = decorator(ContextManager) def contextmanager(func): # Enable Pylint config: contextmanager-decorators=decorator.contextmanager return _contextmanager(func) # ############################ dispatch_on ############################ # def append(a, vancestors): """ Append ``a`` to the list of the virtual ancestors, unless it is already included. """ add = True for j, va in enumerate(vancestors): if issubclass(va, a): add = False break if issubclass(a, va): vancestors[j] = a add = False if add: vancestors.append(a) # inspired from simplegeneric by P.J. Eby and functools.singledispatch def dispatch_on(*dispatch_args): """ Factory of decorators turning a function into a generic function dispatching on the given arguments. """ assert dispatch_args, 'No dispatch args passed' dispatch_str = '(%s,)' % ', '.join(dispatch_args) def check(arguments, wrong=operator.ne, msg=''): """Make sure one passes the expected number of arguments""" if wrong(len(arguments), len(dispatch_args)): raise TypeError('Expected %d arguments, got %d%s' % (len(dispatch_args), len(arguments), msg)) def gen_func_dec(func): """Decorator turning a function into a generic function""" # first check the dispatch arguments argset = set(getfullargspec(func).args) if not set(dispatch_args) <= argset: raise NameError('Unknown dispatch arguments %s' % dispatch_str) typemap = {} def vancestors(*types): """ Get a list of sets of virtual ancestors for the given types """ check(types) ras = [[] for _ in range(len(dispatch_args))] for types_ in typemap: for t, type_, ra in zip(types, types_, ras): if issubclass(t, type_) and type_ not in t.mro(): append(type_, ra) return [set(ra) for ra in ras] def ancestors(*types): """ Get a list of virtual MROs, one for each type """ check(types) lists = [] for t, vas in zip(types, vancestors(*types)): n_vas = len(vas) if n_vas > 1: raise RuntimeError( 'Ambiguous dispatch for %s: %s' % (t, vas)) elif n_vas == 1: va, = vas mro = type('t', (t, va), {}).mro()[1:] else: mro = t.mro() lists.append(mro[:-1]) # discard t and object return lists def register(*types): """ Decorator to register an implementation for the given types """ check(types) def dec(f): check(getfullargspec(f).args, operator.lt, ' in ' + f.__name__) typemap[types] = f return f return dec def dispatch_info(*types): """ An utility to introspect the dispatch algorithm """ check(types) lst = [] for anc in itertools.product(*ancestors(*types)): lst.append(tuple(a.__name__ for a in anc)) return lst def _dispatch(dispatch_args, *args, **kw): types = tuple(type(arg) for arg in dispatch_args) try: # fast path f = typemap[types] except KeyError: pass else: return f(*args, **kw) combinations = itertools.product(*ancestors(*types)) next(combinations) # the first one has been already tried for types_ in combinations: f = typemap.get(types_) if f is not None: return f(*args, **kw) # else call the default implementation return func(*args, **kw) return FunctionMaker.create( func, 'return _f_(%s, %%(shortsignature)s)' % dispatch_str, dict(_f_=_dispatch), register=register, default=func, typemap=typemap, vancestors=vancestors, ancestors=ancestors, dispatch_info=dispatch_info, __wrapped__=func) gen_func_dec.__name__ = 'dispatch_on' + dispatch_str return gen_func_dec