#!/usr/bin/python # -*- coding: utf-8 -*- # Hive Appier Framework # Copyright (c) 2008-2024 Hive Solutions Lda. # # This file is part of Hive Appier Framework. # # Hive Appier Framework is free software: you can redistribute it and/or modify # it under the terms of the Apache License as published by the Apache # Foundation, either version 2.0 of the License, or (at your option) any # later version. # # Hive Appier Framework is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # Apache License for more details. # # You should have received a copy of the Apache License along with # Hive Appier Framework. If not, see . __author__ = "João Magalhães " """ The author(s) of the module """ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda." """ The copyright for the module """ __license__ = "Apache License, Version 2.0" """ The license for the module """ import os import sys import calendar import datetime import inspect import functools import itertools import contextlib import collections import urllib # @UnusedImport ArgSpec = collections.namedtuple("ArgSpec", ["args", "varargs", "keywords", "defaults"]) @contextlib.contextmanager def ctx_absolute(): root = sys.path.pop(0) try: yield finally: sys.path.insert(0, root) with ctx_absolute(): try: import urllib2 except ImportError: urllib2 = None with ctx_absolute(): try: import httplib except ImportError: httplib = None with ctx_absolute(): try: import http except ImportError: http = None with ctx_absolute(): try: import types except ImportError: types = None with ctx_absolute(): try: import urllib.error except ImportError: pass with ctx_absolute(): try: import urllib.request except ImportError: pass with ctx_absolute(): try: import http.client except ImportError: pass with ctx_absolute(): try: import importlib.util except ImportError: pass try: import HTMLParser except ImportError: import html.parser HTMLParser = html.parser try: import cPickle except ImportError: import pickle cPickle = pickle try: import imp except ImportError: import importlib imp = importlib try: import importlib except ImportError: import imp importlib = imp try: import cStringIO except ImportError: import io cStringIO = io try: import StringIO as _StringIO except ImportError: import io _StringIO = io try: import urlparse as _urlparse except ImportError: import urllib.parse _urlparse = urllib.parse PYTHON_3 = sys.version_info[0] >= 3 """ Global variable that defines if the current Python interpreter is at least Python 3 compliant, this is used to take some of the conversion decision for runtime """ PYTHON_33 = sys.version_info[0] >= 3 and sys.version_info[1] >= 3 """ Global variable that defines if the current Python interpreter is at least Python 3.3 compliant """ PYTHON_35 = sys.version_info[0] >= 3 and sys.version_info[1] >= 5 """ Global variable that defines if the current Python interpreter is at least Python 3.5 compliant """ PYTHON_36 = sys.version_info[0] >= 3 and sys.version_info[1] >= 6 """ Global variable that defines if the current Python interpreter is at least Python 3.6 compliant """ PYTHON_39 = sys.version_info[0] >= 3 and sys.version_info[1] >= 9 """ Global variable that defines if the current Python interpreter is at least Python 3.9 compliant """ PYTHON_ASYNC = PYTHON_35 """ Global variable that defines if the current Python interpreter support the async/await syntax responsible for the easy to use async methods """ PYTHON_ASYNC_GEN = PYTHON_36 """ Global variable that defines if the current Python interpreter support the async/await generator syntax responsible for the async generator methods """ PYTHON_V = int("".join([str(v) for v in sys.version_info[:3]])) """ The Python version integer describing the version of a the interpreter as a set of three integer digits """ if PYTHON_3: LONG = int else: LONG = long # @UndefinedVariable if PYTHON_3: BYTES = bytes else: BYTES = str # @UndefinedVariable if PYTHON_3: UNICODE = str else: UNICODE = unicode # @UndefinedVariable if PYTHON_3: OLD_UNICODE = None else: OLD_UNICODE = unicode # @UndefinedVariable if PYTHON_3: STRINGS = (str,) else: STRINGS = (str, unicode) # @UndefinedVariable if PYTHON_3: ALL_STRINGS = (bytes, str) else: ALL_STRINGS = (bytes, str, unicode) # @UndefinedVariable if PYTHON_3: INTEGERS = (int,) else: INTEGERS = (int, long) # @UndefinedVariable # saves a series of global symbols that are going to be # used latter for some of the legacy operations _ord = ord _chr = chr _str = str _bytes = bytes _range = range try: _xrange = xrange # @UndefinedVariable except Exception: _xrange = None if PYTHON_3: Request = urllib.request.Request else: Request = urllib2.Request if PYTHON_3: HTTPHandler = urllib.request.HTTPHandler else: HTTPHandler = urllib2.HTTPHandler if PYTHON_3: HTTPError = urllib.error.HTTPError else: HTTPError = urllib2.HTTPError if PYTHON_3: HTTPConnection = http.client.HTTPConnection # @UndefinedVariable else: HTTPConnection = httplib.HTTPConnection if PYTHON_3: HTTPSConnection = http.client.HTTPSConnection # @UndefinedVariable else: HTTPSConnection = httplib.HTTPSConnection try: _execfile = execfile # @UndefinedVariable except Exception: _execfile = None try: _reduce = reduce # @UndefinedVariable except Exception: _reduce = None try: _reload = reload # @UndefinedVariable except Exception: _reload = None try: _unichr = unichr # @UndefinedVariable except Exception: _unichr = None def with_meta(meta, *bases): return meta("Class", bases, {}) def eager(iterable): if PYTHON_3: return list(iterable) return iterable def iteritems(associative): if PYTHON_3: return associative.items() return associative.iteritems() def iterkeys(associative): if PYTHON_3: return associative.keys() return associative.iterkeys() def itervalues(associative): if PYTHON_3: return associative.values() return associative.itervalues() def items(associative): if PYTHON_3: return eager(associative.items()) return associative.items() def keys(associative): if PYTHON_3: return eager(associative.keys()) return associative.keys() def values(associative): if PYTHON_3: return eager(associative.values()) return associative.values() def xrange(start, stop=None, step=1): if PYTHON_3: return _range(start, stop, step) if stop else _range(start) return _xrange(start, stop, step) if stop else _range(start) def range(start, stop=None, step=None): if PYTHON_3: return eager(_range(start, stop, step)) if stop else eager(_range(start)) return _range(start, stop, step) if stop else _range(start) def ord(value): if PYTHON_3 and type(value) == int: return value return _ord(value) def chr(value): if PYTHON_3: return _bytes([value]) if type(value) in INTEGERS: return _chr(value) return value def chri(value): if PYTHON_3: return value if type(value) in INTEGERS: return _chr(value) return value def bytes(value, encoding="latin-1", errors="strict", force=False): if not PYTHON_3 and not force: return value if value == None: return value if type(value) == _bytes: return value return value.encode(encoding, errors) def str(value, encoding="latin-1", errors="strict", force=False): if not PYTHON_3 and not force: return value if value == None: return value if type(value) in STRINGS: return value return value.decode(encoding, errors) def u(value, encoding="utf-8", errors="strict", force=False): if PYTHON_3 and not force: return value if value == None: return value if type(value) == UNICODE: return value return value.decode(encoding, errors) def ascii(value, encoding="utf-8", errors="replace"): if is_bytes(value): value = value.decode(encoding, errors) else: value = UNICODE(value) value = value.encode("ascii", errors) value = str(value) return value def orderable(value): if not PYTHON_3: return value return Orderable(value) def is_str(value): return type(value) == _str def is_unicode(value): if PYTHON_3: return type(value) == _str else: return type(value) == unicode # @UndefinedVariable def is_bytes(value): if PYTHON_3: return type(value) == _bytes else: return type(value) == _str # @UndefinedVariable def is_string(value, all=False): target = ALL_STRINGS if all else STRINGS return type(value) in target def is_generator(value): if inspect.isgenerator(value): return True if type(value) in (itertools.chain,): return True if hasattr(value, "_is_generator"): return True return False def is_async_generator(value): if not hasattr(inspect, "isasyncgen"): return False return inspect.isasyncgen(value) def is_unittest(name="unittest"): current_stack = inspect.stack() for stack_frame in current_stack: for program_line in stack_frame[4]: is_unittest = not name in program_line if is_unittest: continue return True return False def execfile(path, global_vars, local_vars=None, encoding="utf-8"): if local_vars == None: local_vars = global_vars if not PYTHON_3: return _execfile(path, global_vars, local_vars) file = open(path, "rb") try: data = file.read() finally: file.close() data = data.decode(encoding) code = compile(data, path, "exec") exec(code, global_vars, local_vars) # @UndefinedVariable def walk(path, visit, arg): for root, dirs, _files in os.walk(path): names = os.listdir(root) visit(arg, root, names) for dir in list(dirs): exists = dir in names not exists and dirs.remove(dir) def getargspec(func): has_full = hasattr(inspect, "getfullargspec") if has_full: return ArgSpec(*inspect.getfullargspec(func)[:4]) else: return inspect.getargspec(func) def has_module(name): if PYTHON_3: try: spec = importlib.util.find_spec(name) except ImportError: return False if spec == None: return False return True try: file, _path, _description = imp.find_module(name) except ImportError: return False if file: file.close() return True def new_module(name): if hasattr(types, "ModuleType"): return types.ModuleType(name) if hasattr(imp, "new_module"): return imp.new_module(name) raise ValueError("No module build method available") def reduce(*args, **kwargs): if PYTHON_3: return functools.reduce(*args, **kwargs) return _reduce(*args, **kwargs) def reload(*args, **kwargs): if PYTHON_3: return importlib.reload(*args, **kwargs) return _reload(*args, **kwargs) def unichr(*args, **kwargs): if PYTHON_3: return _chr(*args, **kwargs) return _unichr(*args, **kwargs) def urlopen(*args, **kwargs): if PYTHON_3: return urllib.request.urlopen(*args, **kwargs) else: return urllib2.urlopen(*args, **kwargs) # @UndefinedVariable def build_opener(*args, **kwargs): if PYTHON_3: return urllib.request.build_opener(*args, **kwargs) else: return urllib2.build_opener(*args, **kwargs) # @UndefinedVariable def to_timestamp(date_time): if PYTHON_33: return date_time.replace(tzinfo=datetime.timezone.utc).timestamp() else: return calendar.timegm(date_time.utctimetuple()) def to_datetime(timestamp): if PYTHON_33: return datetime.datetime.fromtimestamp( timestamp, datetime.timezone.utc ).replace(tzinfo=None) else: return datetime.datetime.utcfromtimestamp(timestamp) def utcfromtimestamp(timestamp): return to_datetime(timestamp) def utc_now(): if PYTHON_33: return datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) else: return datetime.datetime.utcnow() def urlparse(*args, **kwargs): return _urlparse.urlparse(*args, **kwargs) def urlunparse(*args, **kwargs): return _urlparse.urlunparse(*args, **kwargs) def parse_qs(*args, **kwargs): return _urlparse.parse_qs(*args, **kwargs) def urlencode(*args, **kwargs): if PYTHON_3: return urllib.parse.urlencode(*args, **kwargs) else: return urllib.urlencode(*args, **kwargs) # @UndefinedVariable def quote(*args, **kwargs): if PYTHON_3: return urllib.parse.quote(*args, **kwargs) else: return urllib.quote(*args, **kwargs) # @UndefinedVariable def quote_plus(*args, **kwargs): if PYTHON_3: return urllib.parse.quote_plus(*args, **kwargs) else: return urllib.quote_plus(*args, **kwargs) # @UndefinedVariable def unquote(*args, **kwargs): if PYTHON_3: return urllib.parse.unquote(*args, **kwargs) else: return urllib.unquote(*args, **kwargs) # @UndefinedVariable def unquote_plus(*args, **kwargs): if PYTHON_3: return urllib.parse.unquote_plus(*args, **kwargs) else: return urllib.unquote_plus(*args, **kwargs) # @UndefinedVariable def cmp_to_key(*args, **kwargs): if PYTHON_3: return dict(key=functools.cmp_to_key(*args, **kwargs)) # @UndefinedVariable else: return dict(cmp=args[0]) def tobytes(self, *args, **kwargs): if PYTHON_3: return self.tobytes(*args, **kwargs) else: return self.tostring(*args, **kwargs) def tostring(self, *args, **kwargs): if PYTHON_3: return self.tobytes(*args, **kwargs) else: return self.tostring(*args, **kwargs) def StringIO(*args, **kwargs): if PYTHON_3: return cStringIO.StringIO(*args, **kwargs) else: return _StringIO.StringIO(*args, **kwargs) def BytesIO(*args, **kwargs): if PYTHON_3: return cStringIO.BytesIO(*args, **kwargs) else: return cStringIO.StringIO(*args, **kwargs) class Orderable(tuple): """ Simple tuple type wrapper that provides a simple first element ordering, that is compatible with both the Python 2 and Python 3+ infra-structures. """ def __cmp__(self, value): return self[0].__cmp__(value[0]) def __lt__(self, value): return self[0].__lt__(value[0])