2014-07-07 17:48:35 +03:00
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
# not use this file except in compliance with the License. You may obtain
|
|
|
|
# a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
# License for the specific language governing permissions and limitations
|
|
|
|
# under the License.
|
|
|
|
|
2020-09-23 18:46:13 +08:00
|
|
|
from urllib import parse
|
|
|
|
|
2013-09-02 23:42:41 -04:00
|
|
|
|
|
|
|
class HookableMixin(object):
|
|
|
|
"""Mixin so classes can register and run hooks."""
|
|
|
|
_hooks_map = {}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def add_hook(cls, hook_type, hook_func):
|
|
|
|
if hook_type not in cls._hooks_map:
|
|
|
|
cls._hooks_map[hook_type] = []
|
|
|
|
|
|
|
|
cls._hooks_map[hook_type].append(hook_func)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def run_hooks(cls, hook_type, *args, **kwargs):
|
|
|
|
hook_funcs = cls._hooks_map.get(hook_type) or []
|
|
|
|
for hook_func in hook_funcs:
|
|
|
|
hook_func(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
def safe_issubclass(*args):
|
|
|
|
"""Like issubclass, but will just return False if not a class."""
|
|
|
|
|
|
|
|
try:
|
|
|
|
if issubclass(*args):
|
|
|
|
return True
|
|
|
|
except TypeError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return False
|
2015-09-01 19:12:01 -04:00
|
|
|
|
|
|
|
|
|
|
|
def get_function_name(func):
|
2021-07-13 16:52:47 +01:00
|
|
|
return "%s.%s" % (func.__module__, func.__qualname__)
|
2017-11-09 20:27:54 +08:00
|
|
|
|
|
|
|
|
2018-10-08 15:09:39 -07:00
|
|
|
def safe_urlencode(params_dict):
|
|
|
|
"""Workaround incompatible change to urllib.parse
|
|
|
|
|
|
|
|
urllib's parse library used to adhere to RFC 2396 until
|
|
|
|
python 3.7. The library moved from RFC 2396 to RFC 3986
|
|
|
|
for quoting URL strings in python 3.7 and '~' is now
|
|
|
|
included in the set of reserved characters. [1]
|
|
|
|
|
|
|
|
This utility ensures "~" is never encoded.
|
|
|
|
|
|
|
|
See LP 1785283 [2] for more details.
|
|
|
|
[1] https://docs.python.org/3/library/urllib.parse.html#url-quoting
|
|
|
|
[2] https://bugs.launchpad.net/python-manilaclient/+bug/1785283
|
|
|
|
|
|
|
|
:param params_dict can be a list of (k,v) tuples, or a dictionary
|
|
|
|
"""
|
|
|
|
|
|
|
|
parsed_params = parse.urlencode(params_dict)
|
|
|
|
return parsed_params.replace("%7E", "~")
|