dbt-selly/dbt-env/lib/python3.8/site-packages/jsonrpc/utils.py

136 lines
3.9 KiB
Python
Raw Normal View History

2022-03-22 15:13:27 +00:00
""" Utility functions for package."""
from abc import ABCMeta, abstractmethod
import datetime
import decimal
import inspect
import json
import sys
from . import six
class JSONSerializable(six.with_metaclass(ABCMeta, object)):
""" Common functionality for json serializable objects."""
serialize = staticmethod(json.dumps)
deserialize = staticmethod(json.loads)
@abstractmethod
def json(self):
raise NotImplementedError()
@classmethod
def from_json(cls, json_str):
data = cls.deserialize(json_str)
if not isinstance(data, dict):
raise ValueError("data should be dict")
return cls(**data)
class DatetimeDecimalEncoder(json.JSONEncoder):
""" Encoder for datetime and decimal serialization.
Usage: json.dumps(object, cls=DatetimeDecimalEncoder)
NOTE: _iterencode does not work
"""
def default(self, o):
""" Encode JSON.
:return str: A JSON encoded string
"""
if isinstance(o, decimal.Decimal):
return float(o)
if isinstance(o, (datetime.datetime, datetime.date)):
return o.isoformat()
return json.JSONEncoder.default(self, o)
def is_invalid_params_py2(func, *args, **kwargs):
""" Check, whether function 'func' accepts parameters 'args', 'kwargs'.
NOTE: Method is called after funct(*args, **kwargs) generated TypeError,
it is aimed to destinguish TypeError because of invalid parameters from
TypeError from inside the function.
.. versionadded: 1.9.0
"""
funcargs, varargs, varkwargs, defaults = inspect.getargspec(func)
unexpected = set(kwargs.keys()) - set(funcargs)
if len(unexpected) > 0:
return True
params = [funcarg for funcarg in funcargs if funcarg not in kwargs]
funcargs_required = funcargs[:-len(defaults)] \
if defaults is not None \
else funcargs
params_required = [
funcarg for funcarg in funcargs_required
if funcarg not in kwargs
]
return not (len(params_required) <= len(args) <= len(params))
def is_invalid_params_py3(func, *args, **kwargs):
"""
Use inspect.signature instead of inspect.getargspec or
inspect.getfullargspec (based on inspect.signature itself) as it provides
more information about function parameters.
.. versionadded: 1.11.2
"""
signature = inspect.signature(func)
parameters = signature.parameters
unexpected = set(kwargs.keys()) - set(parameters.keys())
if len(unexpected) > 0:
return True
params = [
parameter for name, parameter in parameters.items()
if name not in kwargs
]
params_required = [
param for param in params
if param.default is param.empty
]
return not (len(params_required) <= len(args) <= len(params))
def is_invalid_params(func, *args, **kwargs):
"""
Method:
Validate pre-defined criteria, if any is True - function is invalid
0. func should be callable
1. kwargs should not have unexpected keywords
2. remove kwargs.keys from func.parameters
3. number of args should be <= remaining func.parameters
4. number of args should be >= remaining func.parameters less default
"""
# For builtin functions inspect.getargspec(funct) return error. If builtin
# function generates TypeError, it is because of wrong parameters.
if not inspect.isfunction(func):
return True
if sys.version_info >= (3, 3):
return is_invalid_params_py3(func, *args, **kwargs)
else:
# NOTE: use Python2 method for Python 3.2 as well. Starting from Python
# 3.3 it is recommended to use inspect.signature instead.
# In Python 3.0 - 3.2 inspect.getfullargspec is preferred but these
# versions are almost not supported. Users should consider upgrading.
return is_invalid_params_py2(func, *args, **kwargs)