def Delimited(value, parser=Text, delimiter=u',', encoding=None):
    """
    Parse a value as a delimited list.

    :type  value: `unicode` or `bytes`
    :param value: Text value to parse.

    :type  parser: `callable` taking a `unicode` parameter
    :param parser: Callable to map over the delimited text values.

    :type  delimiter: `unicode`
    :param delimiter: Delimiter text.

    :type  encoding: `bytes`
    :param encoding: Encoding to treat `bytes` values as, defaults to
        ``utf-8``.

    :rtype: `list`
    :return: List of parsed values.
    """
    value = Text(value, encoding)
    if value is None or value == u'':
        return []
    return map(parser, value.split(delimiter))

def Delimited ( value , parser = Text , delimiter = u',' , encoding = None ) : value = Text ( value , encoding ) if value is None or value == u'' : return [ ] return map ( parser , value . split ( delimiter ) )


def Timestamp(value, _divisor=1., tz=UTC, encoding=None):
    """
    Parse a value as a POSIX timestamp in seconds.

    :type  value: `unicode` or `bytes`
    :param value: Text value to parse, which should be the number of seconds
        since the epoch.

    :type  _divisor: `float`
    :param _divisor: Number to divide the value by.

    :type  tz: `tzinfo`
    :param tz: Timezone, defaults to UTC.

    :type  encoding: `bytes`
    :param encoding: Encoding to treat `bytes` values as, defaults to
        ``utf-8``.

    :rtype: `datetime.datetime`
    :return: Parsed datetime or ``None`` if ``value`` could not be parsed.
    """
    value = Float(value, encoding)
    if value is not None:
        value = value / _divisor
        return datetime.fromtimestamp(value, tz)
    return None

def Timestamp ( value , _divisor = 1. , tz = UTC , encoding = None ) : value = Float ( value , encoding ) if value is not None : value = value / _divisor return datetime . fromtimestamp ( value , tz ) return None

Parse a value as a POSIX timestamp in seconds .


def parse(expected, query):
    """
    Parse query parameters.

    :type  expected: `dict` mapping `bytes` to `callable`
    :param expected: Mapping of query argument names to argument parsing
        callables.

    :type  query: `dict` mapping `bytes` to `list` of `bytes`
    :param query: Mapping of query argument names to lists of argument values,
        this is the form that Twisted Web's `IRequest.args
        <twisted:twisted.web.iweb.IRequest.args>` value takes.

    :rtype: `dict` mapping `bytes` to `object`
    :return: Mapping of query argument names to parsed argument values.
    """
    return dict(
        (key, parser(query.get(key, [])))
        for key, parser in expected.items())

def parse ( expected , query ) : return dict ( ( key , parser ( query . get ( key , [ ] ) ) ) for key , parser in expected . items ( ) )


def put(self, metrics):
        """
        Put metrics to cloudwatch. Metric shoult be instance or list of
        instances of CloudWatchMetric
        """
        if type(metrics) == list:
            for metric in metrics:
                self.c.put_metric_data(**metric)
        else:
            self.c.put_metric_data(**metrics)

def put ( self , metrics ) : if type ( metrics ) == list : for metric in metrics : self . c . put_metric_data ( * * metric ) else : self . c . put_metric_data ( * * metrics )

Put metrics to cloudwatch . Metric shoult be instance or list of instances of CloudWatchMetric


def _renderResource(resource, request):
    """
    Render a given resource.

    See `IResource.render <twisted:twisted.web.resource.IResource.render>`.
    """
    meth = getattr(resource, 'render_' + nativeString(request.method), None)
    if meth is None:
        try:
            allowedMethods = resource.allowedMethods
        except AttributeError:
            allowedMethods = _computeAllowedMethods(resource)
        raise UnsupportedMethod(allowedMethods)
    return meth(request)

def _renderResource ( resource , request ) : meth = getattr ( resource , 'render_' + nativeString ( request . method ) , None ) if meth is None : try : allowedMethods = resource . allowedMethods except AttributeError : allowedMethods = _computeAllowedMethods ( resource ) raise UnsupportedMethod ( allowedMethods ) return meth ( request )


def _adaptToResource(self, result):
        """
        Adapt a result to `IResource`.

        Several adaptions are tried they are, in order: ``None``,
        `IRenderable <twisted:twisted.web.iweb.IRenderable>`, `IResource
        <twisted:twisted.web.resource.IResource>`, and `URLPath
        <twisted:twisted.python.urlpath.URLPath>`. Anything else is returned as
        is.

        A `URLPath <twisted:twisted.python.urlpath.URLPath>` is treated as
        a redirect.
        """
        if result is None:
            return NotFound()

        spinneretResource = ISpinneretResource(result, None)
        if spinneretResource is not None:
            return SpinneretResource(spinneretResource)

        renderable = IRenderable(result, None)
        if renderable is not None:
            return _RenderableResource(renderable)

        resource = IResource(result, None)
        if resource is not None:
            return resource

        if isinstance(result, URLPath):
            return Redirect(str(result))

        return result

def _adaptToResource ( self , result ) : if result is None : return NotFound ( ) spinneretResource = ISpinneretResource ( result , None ) if spinneretResource is not None : return SpinneretResource ( spinneretResource ) renderable = IRenderable ( result , None ) if renderable is not None : return _RenderableResource ( renderable ) resource = IResource ( result , None ) if resource is not None : return resource if isinstance ( result , URLPath ) : return Redirect ( str ( result ) ) return result


def _handleRenderResult(self, request, result):
        """
        Handle the result from `IResource.render`.

        If the result is a `Deferred` then return `NOT_DONE_YET` and add
        a callback to write the result to the request when it arrives.
        """
        def _requestFinished(result, cancel):
            cancel()
            return result

        if not isinstance(result, Deferred):
            result = succeed(result)

        def _whenDone(result):
            render = getattr(result, 'render', lambda request: result)
            renderResult = render(request)
            if renderResult != NOT_DONE_YET:
                request.write(renderResult)
                request.finish()
            return result
        request.notifyFinish().addBoth(_requestFinished, result.cancel)
        result.addCallback(self._adaptToResource)
        result.addCallback(_whenDone)
        result.addErrback(request.processingFailed)
        return NOT_DONE_YET

def _handleRenderResult ( self , request , result ) : def _requestFinished ( result , cancel ) : cancel ( ) return result if not isinstance ( result , Deferred ) : result = succeed ( result ) def _whenDone ( result ) : render = getattr ( result , 'render' , lambda request : result ) renderResult = render ( request ) if renderResult != NOT_DONE_YET : request . write ( renderResult ) request . finish ( ) return result request . notifyFinish ( ) . addBoth ( _requestFinished , result . cancel ) result . addCallback ( self . _adaptToResource ) result . addCallback ( _whenDone ) result . addErrback ( request . processingFailed ) return NOT_DONE_YET

Handle the result from IResource . render .


def _negotiateHandler(self, request):
        """
        Negotiate a handler based on the content types acceptable to the
        client.

        :rtype: 2-`tuple` of `twisted.web.iweb.IResource` and `bytes`
        :return: Pair of a resource and the content type.
        """
        accept = _parseAccept(request.requestHeaders.getRawHeaders('Accept'))
        for contentType in accept.keys():
            handler = self._acceptHandlers.get(contentType.lower())
            if handler is not None:
                return handler, handler.contentType

        if self._fallback:
            handler = self._handlers[0]
            return handler, handler.contentType
        return NotAcceptable(), None

def _negotiateHandler ( self , request ) : accept = _parseAccept ( request . requestHeaders . getRawHeaders ( 'Accept' ) ) for contentType in accept . keys ( ) : handler = self . _acceptHandlers . get ( contentType . lower ( ) ) if handler is not None : return handler , handler . contentType if self . _fallback : handler = self . _handlers [ 0 ] return handler , handler . contentType return NotAcceptable ( ) , None

Negotiate a handler based on the content types acceptable to the client .


def _parseAccept(headers):
    """
    Parse and sort an ``Accept`` header.

    The header is sorted according to the ``q`` parameter for each header value.

    @rtype: `OrderedDict` mapping `bytes` to `dict`
    @return: Mapping of media types to header parameters.
    """
    def sort(value):
        return float(value[1].get('q', 1))
    return OrderedDict(sorted(_splitHeaders(headers), key=sort, reverse=True))

def _parseAccept ( headers ) : def sort ( value ) : return float ( value [ 1 ] . get ( 'q' , 1 ) ) return OrderedDict ( sorted ( _splitHeaders ( headers ) , key = sort , reverse = True ) )


def _splitHeaders(headers):
    """
    Split an HTTP header whose components are separated with commas.

    Each component is then split on semicolons and the component arguments
    converted into a `dict`.

    @return: `list` of 2-`tuple` of `bytes`, `dict`
    @return: List of header arguments and mapping of component argument names
        to values.
    """
    return [cgi.parse_header(value)
            for value in chain.from_iterable(
                s.split(',') for s in headers
                if s)]

def _splitHeaders ( headers ) : return [ cgi . parse_header ( value ) for value in chain . from_iterable ( s . split ( ',' ) for s in headers if s ) ]

Split an HTTP header whose components are separated with commas .


def contentEncoding(requestHeaders, encoding=None):
    """
    Extract an encoding from a ``Content-Type`` header.

    @type  requestHeaders: `twisted.web.http_headers.Headers`
    @param requestHeaders: Request headers.

    @type  encoding: `bytes`
    @param encoding: Default encoding to assume if the ``Content-Type``
        header is lacking one. Defaults to ``UTF-8``.

    @rtype: `bytes`
    @return: Content encoding.
    """
    if encoding is None:
        encoding = b'utf-8'
    headers = _splitHeaders(
        requestHeaders.getRawHeaders(b'Content-Type', []))
    if headers:
        return headers[0][1].get(b'charset', encoding)
    return encoding

def contentEncoding ( requestHeaders , encoding = None ) : if encoding is None : encoding = b'utf-8' headers = _splitHeaders ( requestHeaders . getRawHeaders ( b'Content-Type' , [ ] ) ) if headers : return headers [ 0 ] [ 1 ] . get ( b'charset' , encoding ) return encoding

Extract an encoding from a Content - Type header .


def maybe(f, default=None):
    """
    Create a nil-safe callable decorator.

    If the wrapped callable receives ``None`` as its argument, it will return
    ``None`` immediately.
    """
    @wraps(f)
    def _maybe(x, *a, **kw):
        if x is None:
            return default
        return f(x, *a, **kw)
    return _maybe

def maybe ( f , default = None ) : @ wraps ( f ) def _maybe ( x , * a , * * kw ) : if x is None : return default return f ( x , * a , * * kw ) return _maybe

Create a nil - safe callable decorator .


def settings(path=None, with_path=None):
    """
    Get or set `Settings._wrapped`

    :param str path: a python module file,
        if user set it,write config to `Settings._wrapped`
    :param str with_path: search path
    :return: A instance of `Settings`
    """

    if path:
        Settings.bind(path, with_path=with_path)

    return Settings._wrapped

def settings ( path = None , with_path = None ) : if path : Settings . bind ( path , with_path = with_path ) return Settings . _wrapped


def bind(mod_path, with_path=None):
        """
        bind user variable to `_wrapped`

        .. note::

            you don't need call this method by yourself.

            program will call it in  `cliez.parser.parse`

        .. expection::

            if path is not correct,will cause an `ImportError`

        :param str mod_path: module path, *use dot style,'mod.mod1'*
        :param str with_path: add path to `sys.path`,
            if path is file,use its parent.
        :return: A instance of `Settings`
        """

        if with_path:
            if os.path.isdir(with_path):
                sys.path.insert(0, with_path)
            else:
                sys.path.insert(0, with_path.rsplit('/', 2)[0])
            pass

        # raise `ImportError` mod_path if not exist
        mod = importlib.import_module(mod_path)

        settings = Settings()

        for v in dir(mod):
            if v[0] == '_' or type(getattr(mod, v)).__name__ == 'module':
                continue
            setattr(settings, v, getattr(mod, v))
            pass

        Settings._path = mod_path
        Settings._wrapped = settings

        return settings


def get_version():
    """
    Get the version from version module without importing more than
    necessary.
    """
    version_module_path = os.path.join(
        os.path.dirname(__file__), "txspinneret", "_version.py")
    # The version module contains a variable called __version__
    with open(version_module_path) as version_module:
        exec(version_module.read())
    return locals()["__version__"]

Get the version from version module without importing more than necessary .


def send(self, use_open_peers=True, queue=True, **kw):
        """
        send a transaction immediately. Failed transactions are picked up by the TxBroadcaster

        :param ip: specific peer IP to send tx to
        :param port: port of specific peer
        :param use_open_peers: use Arky's broadcast method
        """

        if not use_open_peers:
            ip = kw.get('ip')
            port = kw.get('port')
            peer = 'http://{}:{}'.format(ip, port)
            res = arky.rest.POST.peer.transactions(peer=peer, transactions=[self.tx.tx])

        else:
            res = arky.core.sendPayload(self.tx.tx)

        if self.tx.success != '0.0%':
            self.tx.error = None
            self.tx.success = True
        else:
            self.tx.error = res['messages']
            self.tx.success = False

        self.tx.tries += 1
        self.tx.res = res

        if queue:
            self.tx.send = True

        self.__save()
        return res

def send ( self , use_open_peers = True , queue = True , * * kw ) : if not use_open_peers : ip = kw . get ( 'ip' ) port = kw . get ( 'port' ) peer = 'http://{}:{}' . format ( ip , port ) res = arky . rest . POST . peer . transactions ( peer = peer , transactions = [ self . tx . tx ] ) else : res = arky . core . sendPayload ( self . tx . tx ) if self . tx . success != '0.0%' : self . tx . error = None self . tx . success = True else : self . tx . error = res [ 'messages' ] self . tx . success = False self . tx . tries += 1 self . tx . res = res if queue : self . tx . send = True self . __save ( ) return res

send a transaction immediately . Failed transactions are picked up by the TxBroadcaster


def check_confirmations_or_resend(self, use_open_peers=False, **kw):
        """
        check if a tx is confirmed, else resend it.

        :param use_open_peers: select random peers fro api/peers endpoint
        """
        if self.confirmations() == 0:
            self.send(use_open_peers, **kw)

def check_confirmations_or_resend ( self , use_open_peers = False , * * kw ) : if self . confirmations ( ) == 0 : self . send ( use_open_peers , * * kw )

check if a tx is confirmed else resend it .


def command_list():
    """
    Get sub-command list

    .. note::

        Don't use logger handle this function errors.

        Because the error should be a code error,not runtime error.

    :return: `list` matched sub-parser
    """
    from cliez.conf import COMPONENT_ROOT

    root = COMPONENT_ROOT

    if root is None:
        sys.stderr.write("cliez.conf.COMPONENT_ROOT not set.\n")
        sys.exit(2)
        pass

    if not os.path.exists(root):
        sys.stderr.write(
            "please set a valid path for `cliez.conf.COMPONENT_ROOT`\n")
        sys.exit(2)
        pass

    try:
        path = os.listdir(os.path.join(root, 'components'))
        return [f[:-3] for f in path if
                f.endswith('.py') and f != '__init__.py']
    except FileNotFoundError:
        return []


def append_arguments(klass, sub_parsers, default_epilog, general_arguments):
    """
    Add class options to argparser options.

    :param cliez.component.Component klass: subclass of Component
    :param Namespace sub_parsers:
    :param str default_epilog: default_epilog
    :param list general_arguments: global options, defined by user
    :return: Namespace subparser
    """

    entry_name = hump_to_underscore(klass.__name__).replace(
        '_component',
        '')

    # set sub command document
    epilog = default_epilog if default_epilog \
        else 'This tool generate by `cliez` ' \
             'https://www.github.com/wangwenpei/cliez'

    sub_parser = sub_parsers.add_parser(entry_name, help=klass.__doc__,
                                        epilog=epilog)
    sub_parser.description = klass.add_arguments.__doc__

    # add slot arguments
    if hasattr(klass, 'add_slot_args'):
        slot_args = klass.add_slot_args() or []
        for v in slot_args:
            sub_parser.add_argument(*v[0], **v[1])
        sub_parser.description = klass.add_slot_args.__doc__
        pass

    user_arguments = klass.add_arguments() or []

    for v in user_arguments:
        sub_parser.add_argument(*v[0], **v[1])

    if not klass.exclude_global_option:
        for v in general_arguments:
            sub_parser.add_argument(*v[0], **v[1])

    return sub_parser

Add class options to argparser options .


def parse(parser, argv=None, settings_key='settings', no_args_func=None):
    """
    parser cliez app

    :param argparse.ArgumentParser parser: an instance
        of argparse.ArgumentParser
    :param argv: argument list,default is `sys.argv`
    :type argv: list or tuple

    :param str settings: settings option name,
        default is settings.

    :param object no_args_func: a callable object.if no sub-parser matched,
        parser will call it.

    :return:  an instance of `cliez.component.Component` or its subclass
    """

    argv = argv or sys.argv
    commands = command_list()

    if type(argv) not in [list, tuple]:
        raise TypeError("argv only can be list or tuple")

    # match sub-parser
    if len(argv) >= 2 and argv[1] in commands:
        sub_parsers = parser.add_subparsers()
        class_name = argv[1].capitalize() + 'Component'

        from cliez.conf import (COMPONENT_ROOT,
                                LOGGING_CONFIG,
                                EPILOG,
                                GENERAL_ARGUMENTS)

        sys.path.insert(0, os.path.dirname(COMPONENT_ROOT))
        mod = importlib.import_module(
            '{}.components.{}'.format(os.path.basename(COMPONENT_ROOT),
                                      argv[1]))

        # dynamic load component
        klass = getattr(mod, class_name)
        sub_parser = append_arguments(klass, sub_parsers, EPILOG,
                                      GENERAL_ARGUMENTS)
        options = parser.parse_args(argv[1:])

        settings = Settings.bind(
            getattr(options, settings_key)
        ) if settings_key and hasattr(options, settings_key) else None

        obj = klass(parser, sub_parser, options, settings)

        # init logger
        logger_level = logging.CRITICAL
        if hasattr(options, 'verbose'):
            if options.verbose == 1:
                logger_level = logging.ERROR
            elif options.verbose == 2:
                logger_level = logging.WARNING
            elif options.verbose == 3:
                logger_level = logging.INFO
                obj.logger.setLevel(logging.INFO)
            pass

        if hasattr(options, 'debug') and options.debug:
            logger_level = logging.DEBUG
            # http lib use a strange way to logging
            try:
                import http.client as http_client
                http_client.HTTPConnection.debuglevel = 1
            except Exception:
                # do nothing
                pass
            pass

        loggers = LOGGING_CONFIG['loggers']
        for k, v in loggers.items():
            v.setdefault('level', logger_level)
            if logger_level in [logging.INFO, logging.DEBUG]:
                v['handlers'] = ['stdout']
            pass

        logging_config.dictConfig(LOGGING_CONFIG)
        # this may not necessary
        # obj.logger.setLevel(logger_level)

        obj.run(options)

        # return object to make unit test easy
        return obj

    # print all sub commands when user set.
    if not parser.description and len(commands):
        sub_parsers = parser.add_subparsers()
        [sub_parsers.add_parser(v) for v in commands]
        pass
    pass

    options = parser.parse_args(argv[1:])
    if no_args_func and callable(no_args_func):
        return no_args_func(options)
    else:
        parser._print_message("nothing to do...\n")
    pass

def
parse
(
parser
,
argv
=
,
settings_key
=
'settings'
,
no_args_func
=
)
:
argv
=
argv
or
sys
.
argv
commands
=
command_list
(
)
if
type
(
argv
)
not
in
[
list
,
tuple
]
:
raise
TypeError
(
"argv only can be list or tuple"
)
# match sub-parser
if
len
(
argv
)
>=
2
and
argv
[
1
]
in
commands
:
sub_parsers
=
parser
.
add_subparsers
(
)
class_name
=
argv
[
1
]
.
capitalize
(
)
+
'Component'
from
cliez
.
conf
import
(
COMPONENT_ROOT
,
LOGGING_CONFIG
,
EPILOG
,
GENERAL_ARGUMENTS
)
sys
.
path
.
insert
(
0
,
os
.
path
.
dirname
(
COMPONENT_ROOT
)
)
mod
=
importlib
.
import_module
(
'{}.components.{}'
.
format
(
os
.
path
.
basename
(
COMPONENT_ROOT
)
,
argv
[
1
]
)
)
# dynamic load component
klass
=
getattr
(
mod
,
class_name
)
sub_parser
=
append_arguments
(
klass
,
sub_parsers
,
EPILOG
,
GENERAL_ARGUMENTS
)
options
=
parser
.
parse_args
(
argv
[
1
:
]
)
settings
=
Settings
.
bind
(
getattr
(
options
,
settings_key
)
)
if
settings_key
and
hasattr
(
options
,
settings_key
)
else
obj
=
klass
(
parser
,
sub_parser
,
options
,
settings
)
# init logger
logger_level
=
logging
.
CRITICAL
if
hasattr
(
options
,
'verbose'
)
:
if
options
.
verbose
==
1
:
logger_level
=
logging
.
ERROR
elif
options
.
verbose
==
2
:
logger_level
=
logging
.
WARNING
elif
options
.
verbose
==
3
:
logger_level
=
logging
.
INFO
obj
.
logger
.
setLevel
(
logging
.
INFO
)
pass
if
hasattr
(
options
,
'debug'
)
and
options
.
debug
:
logger_level
=
logging
.
DEBUG
# http lib use a strange way to logging
try
:
import
http
.
client
as
http_client
http_client
.
HTTPConnection
.
debuglevel
=
1
except
Exception
:
# do nothing
pass
pass
loggers
=
LOGGING_CONFIG
[
'loggers'
]
for
k
,
v
in
loggers
.
items
(
)
:
v
.
setdefault
(
'level'
,
logger_level
)
if
logger_level
in
[
logging
.
INFO
,
logging
.
DEBUG
]
:
v
[
'handlers'
]
=
[
'stdout'
]
pass
logging_config
.
dictConfig
(
LOGGING_CONFIG
)
# this may not necessary
# obj.logger.setLevel(logger_level)
obj
.
run
(
options
)
# return object to make unit test easy
return
obj
# print all sub commands when user set.
if
not
parser
.
description
and
len
(
commands
)
:
sub_parsers
=
parser
.
add_subparsers
(
)
[
sub_parsers
.
add_parser
(
v
)
for
v
in
commands
]
pass
pass
options
=
parser
.
parse_args
(
argv
[
1
:
]
)
if
no_args_func
and
callable
(
no_args_func
)
:
return
no_args_func
(
options
)
else
:
parser
.
_print_message
(
"nothing to do...\n"
)
pass


def hump_to_underscore(name):
    """
    Convert Hump style to underscore

    :param name: Hump Character
    :return: str
    """
    new_name = ''

    pos = 0
    for c in name:
        if pos == 0:
            new_name = c.lower()
        elif 65 <= ord(c) <= 90:
            new_name += '_' + c.lower()
            pass
        else:
            new_name += c
        pos += 1
        pass
    return new_name

def hump_to_underscore ( name ) : new_name = '' pos = 0 for c in name : if pos == 0 : new_name = c . lower ( ) elif 65 <= ord ( c ) <= 90 : new_name += '_' + c . lower ( ) pass else : new_name += c pos += 1 pass return new_name


def get_fuel_prices(self) -> GetFuelPricesResponse:
        """Fetches fuel prices for all stations."""
        response = requests.get(
            '{}/prices'.format(API_URL_BASE),
            headers=self._get_headers(),
            timeout=self._timeout,
        )

        if not response.ok:
            raise FuelCheckError.create(response)

        return GetFuelPricesResponse.deserialize(response.json())

def get_fuel_prices ( self ) -> GetFuelPricesResponse : response = requests . get ( '{}/prices' . format ( API_URL_BASE ) , headers = self . _get_headers ( ) , timeout = self . _timeout , ) if not response . ok : raise FuelCheckError . create ( response ) return GetFuelPricesResponse . deserialize ( response . json ( ) )


def get_fuel_prices_for_station(
            self,
            station: int
    ) -> List[Price]:
        """Gets the fuel prices for a specific fuel station."""
        response = requests.get(
            '{}/prices/station/{}'.format(API_URL_BASE, station),
            headers=self._get_headers(),
            timeout=self._timeout,
        )

        if not response.ok:
            raise FuelCheckError.create(response)

        data = response.json()
        return [Price.deserialize(data) for data in data['prices']]

def get_fuel_prices_for_station ( self , station : int ) -> List [ Price ] : response = requests . get ( '{}/prices/station/{}' . format ( API_URL_BASE , station ) , headers = self . _get_headers ( ) , timeout = self . _timeout , ) if not response . ok : raise FuelCheckError . create ( response ) data = response . json ( ) return [ Price . deserialize ( data ) for data in data [ 'prices' ] ]

Gets the fuel prices for a specific fuel station .


def get_fuel_prices_within_radius(
            self, latitude: float, longitude: float, radius: int,
            fuel_type: str, brands: Optional[List[str]] = None
    ) -> List[StationPrice]:
        """Gets all the fuel prices within the specified radius."""

        if brands is None:
            brands = []
        response = requests.post(
            '{}/prices/nearby'.format(API_URL_BASE),
            json={
                'fueltype': fuel_type,
                'latitude': latitude,
                'longitude': longitude,
                'radius': radius,
                'brand': brands,
            },
            headers=self._get_headers(),
            timeout=self._timeout,
        )

        if not response.ok:
            raise FuelCheckError.create(response)

        data = response.json()
        stations = {
            station['code']: Station.deserialize(station)
            for station in data['stations']
        }
        station_prices = []  # type: List[StationPrice]
        for serialized_price in data['prices']:
            price = Price.deserialize(serialized_price)
            station_prices.append(StationPrice(
                price=price,
                station=stations[price.station_code]
            ))

        return station_prices

def
get_fuel_prices_within_radius
(
self
,
latitude
:
float
,
longitude
:
float
,
radius
:
int
,
fuel_type
:
str
,
brands
:
Optional
[
List
[
str
]
]
=
)
->
List
[
StationPrice
]
:
if
brands
is
:
brands
=
[
]
response
=
requests
.
post
(
'{}/prices/nearby'
.
format
(
API_URL_BASE
)
,
json
=
{
'fueltype'
:
fuel_type
,
'latitude'
:
latitude
,
'longitude'
:
longitude
,
'radius'
:
radius
,
'brand'
:
brands
,
}
,
headers
=
self
.
_get_headers
(
)
,
timeout
=
self
.
_timeout
,
)
if
not
response
.
ok
:
raise
FuelCheckError
.
create
(
response
)
data
=
response
.
json
(
)
stations
=
{
station
[
'code'
]
:
Station
.
deserialize
(
station
)
for
station
in
data
[
'stations'
]
}
station_prices
=
[
]
# type: List[StationPrice]
for
serialized_price
in
data
[
'prices'
]
:
price
=
Price
.
deserialize
(
serialized_price
)
station_prices
.
append
(
StationPrice
(
price
=
price
,
station
=
stations
[
price
.
station_code
]
)
)
return
station_prices

Gets all the fuel prices within the specified radius .


def get_fuel_price_trends(self, latitude: float, longitude: float,
                              fuel_types: List[str]) -> PriceTrends:
        """Gets the fuel price trends for the given location and fuel types."""
        response = requests.post(
            '{}/prices/trends/'.format(API_URL_BASE),
            json={
                'location': {
                    'latitude': latitude,
                    'longitude': longitude,
                },
                'fueltypes': [{'code': type} for type in fuel_types],
            },
            headers=self._get_headers(),
            timeout=self._timeout,
        )

        if not response.ok:
            raise FuelCheckError.create(response)

        data = response.json()
        return PriceTrends(
            variances=[
                Variance.deserialize(variance)
                for variance in data['Variances']
            ],
            average_prices=[
                AveragePrice.deserialize(avg_price)
                for avg_price in data['AveragePrices']
            ]
        )

def get_fuel_price_trends ( self , latitude : float , longitude : float , fuel_types : List [ str ] ) -> PriceTrends : response = requests . post ( '{}/prices/trends/' . format ( API_URL_BASE ) , json = { 'location' : { 'latitude' : latitude , 'longitude' : longitude , } , 'fueltypes' : [ { 'code' : type } for type in fuel_types ] , } , headers = self . _get_headers ( ) , timeout = self . _timeout , ) if not response . ok : raise FuelCheckError . create ( response ) data = response . json ( ) return PriceTrends ( variances = [ Variance . deserialize ( variance ) for variance in data [ 'Variances' ] ] , average_prices = [ AveragePrice . deserialize ( avg_price ) for avg_price in data [ 'AveragePrices' ] ] )

Gets the fuel price trends for the given location and fuel types .


def get_reference_data(
            self,
            modified_since: Optional[datetime.datetime] = None
    ) -> GetReferenceDataResponse:
        """
        Fetches API reference data.

        :param modified_since: The response will be empty if no
        changes have been made to the reference data since this
        timestamp, otherwise all reference data will be returned.
        """

        if modified_since is None:
            modified_since = datetime.datetime(year=2010, month=1, day=1)

        response = requests.get(
            '{}/lovs'.format(API_URL_BASE),
            headers={
                'if-modified-since': self._format_dt(modified_since),
                **self._get_headers(),
            },
            timeout=self._timeout,
        )

        if not response.ok:
            raise FuelCheckError.create(response)

        # return response.text
        return GetReferenceDataResponse.deserialize(response.json())

def
get_reference_data
(
self
,
modified_since
:
Optional
[
datetime
.
datetime
]
=
)
->
GetReferenceDataResponse
:
if
modified_since
is
:
modified_since
=
datetime
.
datetime
(
year
=
2010
,
month
=
1
,
day
=
1
)
response
=
requests
.
get
(
'{}/lovs'
.
format
(
API_URL_BASE
)
,
headers
=
{
'if-modified-since'
:
self
.
_format_dt
(
modified_since
)
,
*
*
self
.
_get_headers
(
)
,
}
,
timeout
=
self
.
_timeout
,
)
if
not
response
.
ok
:
raise
FuelCheckError
.
create
(
response
)
# return response.text
return
GetReferenceDataResponse
.
deserialize
(
response
.
json
(
)
)


def pre(self, command, output_dir, vars):
        """
        Called before template is applied.
        """
        # import pdb;pdb.set_trace()
        vars['license_name'] = 'Apache'
        vars['year'] = time.strftime('%Y', time.localtime())

def
pre
(
self
,
command
,
output_dir
,
vars
)
:
# import pdb;pdb.set_trace()
vars
[
'license_name'
]
=
'Apache'
vars
[
'year'
]
=
time
.
strftime
(
'%Y'
,
time
.
localtime
(
)
)


def Text(name, encoding=None):
    """
    Match a route parameter.

    `Any` is a synonym for `Text`.

    :type  name: `bytes`
    :param name: Route parameter name.

    :type  encoding: `bytes`
    :param encoding: Default encoding to assume if the ``Content-Type``
        header is lacking one.

    :return: ``callable`` suitable for use with `route` or `subroute`.
    """
    def _match(request, value):
        return name, query.Text(
            value,
            encoding=contentEncoding(request.requestHeaders, encoding))
    return _match

def Text ( name , encoding = None ) : def _match ( request , value ) : return name , query . Text ( value , encoding = contentEncoding ( request . requestHeaders , encoding ) ) return _match


def Integer(name, base=10, encoding=None):
    """
    Match an integer route parameter.

    :type  name: `bytes`
    :param name: Route parameter name.

    :type  base: `int`
    :param base: Base to interpret the value in.

    :type  encoding: `bytes`
    :param encoding: Default encoding to assume if the ``Content-Type``
        header is lacking one.

    :return: ``callable`` suitable for use with `route` or `subroute`.
    """
    def _match(request, value):
        return name, query.Integer(
            value,
            base=base,
            encoding=contentEncoding(request.requestHeaders, encoding))
    return _match

def Integer ( name , base = 10 , encoding = None ) : def _match ( request , value ) : return name , query . Integer ( value , base = base , encoding = contentEncoding ( request . requestHeaders , encoding ) ) return _match


def _matchRoute(components, request, segments, partialMatching):
    """
    Match a request path against our path components.

    The path components are always matched relative to their parent is in the
    resource hierarchy, in other words it is only possible to match URIs nested
    more deeply than the parent resource.

    :type  components: ``iterable`` of `bytes` or `callable`
    :param components: Iterable of path components, to match against the
        request, either static strings or dynamic parameters. As a convenience,
        a single `bytes` component containing ``/`` may be given instead of
        manually separating the components. If no components are given the null
        route is matched, this is the case where ``segments`` is empty.

    :type  segments: ``sequence`` of `bytes`
    :param segments: Sequence of path segments, from the request, to match
        against.

    :type  partialMatching: `bool`
    :param partialMatching: Allow partial matching against the request path?

    :rtype: 2-`tuple` of `dict` keyed on `bytes` and `list` of `bytes`
    :return: Pair of parameter results, mapping parameter names to processed
        values, and a list of the remaining request path segments. If there is
        no route match the result will be ``None`` and the original request path
        segments.
    """
    if len(components) == 1 and isinstance(components[0], bytes):
        components = components[0]
        if components[:1] == '/':
            components = components[1:]
        components = components.split('/')

    results = OrderedDict()
    NO_MATCH = None, segments
    remaining = list(segments)

    # Handle the null route.
    if len(segments) == len(components) == 0:
        return results, remaining

    for us, them in izip_longest(components, segments):
        if us is None:
            if partialMatching:
                # We've matched all of our components, there might be more
                # segments for something else to process.
                break
            else:
                return NO_MATCH
        elif them is None:
            # We've run out of path segments to match, so this route can't be
            # the matching one.
            return NO_MATCH

        if callable(us):
            name, match = us(request, them)
            if match is None:
                return NO_MATCH
            results[name] = match
        elif us != them:
            return NO_MATCH
        remaining.pop(0)

    return results, remaining

Match a request path against our path components .


def routedResource(f, routerAttribute='router'):
    """
    Decorate a router-producing callable to instead produce a resource.

    This simply produces a new callable that invokes the original callable, and
    calls ``resource`` on the ``routerAttribute``.

    If the router producer has multiple routers the attribute can be altered to
    choose the appropriate one, for example:

    .. code-block:: python

        class _ComplexRouter(object):
            router = Router()
            privateRouter = Router()

            @router.route('/')
            def publicRoot(self, request, params):
                return SomethingPublic(...)

            @privateRouter.route('/')
            def privateRoot(self, request, params):
                return SomethingPrivate(...)

        PublicResource = routedResource(_ComplexRouter)
        PrivateResource = routedResource(_ComplexRouter, 'privateRouter')

    :type  f: ``callable``
    :param f: Callable producing an object with a `Router` attribute, for
        example, a type.

    :type  routerAttribute: `str`
    :param routerAttribute: Name of the `Router` attribute on the result of
        calling ``f``.

    :rtype: `callable`
    :return: Callable producing an `IResource`.
    """
    return wraps(f)(
        lambda *a, **kw: getattr(f(*a, **kw), routerAttribute).resource())

def routedResource ( f , routerAttribute = 'router' ) : return wraps ( f ) ( lambda * a , * * kw : getattr ( f ( * a , * * kw ) , routerAttribute ) . resource ( ) )

Decorate a router - producing callable to instead produce a resource .


def _forObject(self, obj):
        """
        Create a new `Router` instance, with it's own set of routes, for
        ``obj``.
        """
        router = type(self)()
        router._routes = list(self._routes)
        router._self = obj
        return router

def _forObject ( self , obj ) : router = type ( self ) ( ) router . _routes = list ( self . _routes ) router . _self = obj return router

Create a new Router instance with it s own set of routes for obj .


def _addRoute(self, f, matcher):
        """
        Add a route handler and matcher to the collection of possible routes.
        """
        self._routes.append((f.func_name, f, matcher))

def _addRoute ( self , f , matcher ) : self . _routes . append ( ( f . func_name , f , matcher ) )

Add a route handler and matcher to the collection of possible routes .


def route(self, *components):
        """
        See `txspinneret.route.route`.

        This decorator can be stacked with itself to specify multiple routes
        with a single handler.
        """
        def _factory(f):
            self._addRoute(f, route(*components))
            return f
        return _factory

def route ( self , * components ) : def _factory ( f ) : self . _addRoute ( f , route ( * components ) ) return f return _factory


def subroute(self, *components):
        """
        See `txspinneret.route.subroute`.

        This decorator can be stacked with itself to specify multiple routes
        with a single handler.
        """
        def _factory(f):
            self._addRoute(f, subroute(*components))
            return f
        return _factory

def subroute ( self , * components ) : def _factory ( f ) : self . _addRoute ( f , subroute ( * components ) ) return f return _factory


def _tempfile(filename):
    """
    Create a NamedTemporaryFile instance to be passed to atomic_writer
    """
    return tempfile.NamedTemporaryFile(mode='w',
                                       dir=os.path.dirname(filename),
                                       prefix=os.path.basename(filename),
                                       suffix=os.fsencode('.tmp'),
                                       delete=False)

def _tempfile ( filename ) : return tempfile . NamedTemporaryFile ( mode = 'w' , dir = os . path . dirname ( filename ) , prefix = os . path . basename ( filename ) , suffix = os . fsencode ( '.tmp' ) , delete = False )


def atomic_write(filename):
    """
    Open a NamedTemoraryFile handle in a context manager
    """
    f = _tempfile(os.fsencode(filename))

    try:
        yield f

    finally:
        f.close()
        # replace the original file with the new temp file (atomic on success)
        os.replace(f.name, filename)


def get_item(filename, uuid):
    """
    Read entry from JSON file
    """
    with open(os.fsencode(str(filename)), "r") as f:
        data = json.load(f)
        results = [i for i in data if i["uuid"] == str(uuid)]
        if results:
            return results
        return None

def get_item ( filename , uuid ) : with open ( os . fsencode ( str ( filename ) ) , "r" ) as f : data = json . load ( f ) results = [ i for i in data if i [ "uuid" ] == str ( uuid ) ] if results : return results return None


def set_item(filename, item):
    """
    Save entry to JSON file
    """
    with atomic_write(os.fsencode(str(filename))) as temp_file:
        with open(os.fsencode(str(filename))) as products_file:
            # load the JSON data into memory
            products_data = json.load(products_file)
        # check if UUID already exists
        uuid_list = [i for i in filter(
            lambda z: z["uuid"] == str(item["uuid"]), products_data)]
        if len(uuid_list) == 0:
            # add the new item to the JSON file
            products_data.append(item)
            # save the new JSON to the temp file
            json.dump(products_data, temp_file)
            return True
        return None

def
set_item
(
filename
,
item
)
:
with
atomic_write
(
os
.
fsencode
(
str
(
filename
)
)
)
as
temp_file
:
with
open
(
os
.
fsencode
(
str
(
filename
)
)
)
as
products_file
:
# load the JSON data into memory
products_data
=
json
.
load
(
products_file
)
# check if UUID already exists
uuid_list
=
[
i
for
i
in
filter
(
lambda
z
:
z
[
"uuid"
]
==
str
(
item
[
"uuid"
]
)
,
products_data
)
]
if
len
(
uuid_list
)
==
0
:
# add the new item to the JSON file
products_data
.
append
(
item
)
# save the new JSON to the temp file
json
.
dump
(
products_data
,
temp_file
)
return
True
return


def update_item(filename, item, uuid):
    """
    Update entry by UUID in the JSON file
    """
    with atomic_write(os.fsencode(str(filename))) as temp_file:
        with open(os.fsencode(str(filename))) as products_file:
            # load the JSON data into memory
            products_data = json.load(products_file)
        # apply modifications to the JSON data wrt UUID
        # TODO: handle this in a neat way
        if 'products' in products_data[-1]:
            # handle orders object
            [products_data[i]["products"][0].update(item) for (
                i, j) in enumerate(products_data) if j["uuid"] == str(uuid)]
        else:
            # handle products object
            [products_data[i].update(item) for (i, j) in enumerate(
                products_data) if j["uuid"] == str(uuid)]
        # save the modified JSON data into the temp file
        json.dump(products_data, temp_file)
        return True


def command_handle(self):
        """Get the number of the shell command."""
        self.__results = self.execute(self.args.command)
        self.close()

        self.logger.debug("results: {}".format(self.__results))
        if not self.__results:
            self.unknown("{} return nothing.".format(self.args.command))
        if len(self.__results) != 1:
            self.unknown(
                "{} return more than one number.".format(
                    self.args.command))
        self.__result = int(self.__results[0])
        self.logger.debug("result: {}".format(self.__result))
        if not isinstance(self.__result, (int, long)):
            self.unknown(
                "{} didn't return single number.".format(
                    self.args.command))

        status = self.ok
        # Compare the vlaue.
        if self.__result > self.args.warning:
            status = self.warning
        if self.__result > self.args.critical:
            status = self.critical

        # Output
        self.shortoutput = "{0} return {1}.".format(
            self.args.command, self.__result)
        [self.longoutput.append(line)
         for line in self.__results if self.__results]
        self.perfdata.append("{command}={result};{warn};{crit};0;".format(
            crit=self.args.critical,
            warn=self.args.warning,
            result=self.__result,
            command=self.args.command))

        # Return status with message to Nagios.
        status(self.output(long_output_limit=None))
        self.logger.debug("Return status and exit to Nagios.")

def
command_handle
(
self
)
:
self
.
__results
=
self
.
execute
(
self
.
args
.
command
)
self
.
close
(
)
self
.
logger
.
debug
(
"results: {}"
.
format
(
self
.
__results
)
)
if
not
self
.
__results
:
self
.
unknown
(
"{} return nothing."
.
format
(
self
.
args
.
command
)
)
if
len
(
self
.
__results
)
!=
1
:
self
.
unknown
(
"{} return more than one number."
.
format
(
self
.
args
.
command
)
)
self
.
__result
=
int
(
self
.
__results
[
0
]
)
self
.
logger
.
debug
(
"result: {}"
.
format
(
self
.
__result
)
)
if
not
isinstance
(
self
.
__result
,
(
int
,
long
)
)
:
self
.
unknown
(
"{} didn't return single number."
.
format
(
self
.
args
.
command
)
)
status
=
self
.
ok
# Compare the vlaue.
if
self
.
__result
>
self
.
args
.
warning
:
status
=
self
.
warning
if
self
.
__result
>
self
.
args
.
critical
:
status
=
self
.
critical
# Output
self
.
shortoutput
=
"{0} return {1}."
.
format
(
self
.
args
.
command
,
self
.
__result
)
[
self
.
longoutput
.
append
(
line
)
for
line
in
self
.
__results
if
self
.
__results
]
self
.
perfdata
.
append
(
"{command}={result};{warn};{crit};0;"
.
format
(
crit
=
self
.
args
.
critical
,
warn
=
self
.
args
.
warning
,
result
=
self
.
__result
,
command
=
self
.
args
.
command
)
)
# Return status with message to Nagios.
status
(
self
.
output
(
long_output_limit
=
)
)
self
.
logger
.
debug
(
"Return status and exit to Nagios."
)


def execute(self, command, timeout=None):
        """Execute a shell command."""
        try:
            self.channel = self.ssh.get_transport().open_session()
        except paramiko.SSHException as e:
            self.unknown("Create channel error: %s" % e)
        try:
            self.channel.settimeout(self.args.timeout if not timeout else timeout)
        except socket.timeout as e:
            self.unknown("Settimeout for channel error: %s" % e)
        try:
            self.logger.debug("command: {}".format(command))
            self.channel.exec_command(command)
        except paramiko.SSHException as e:
            self.unknown("Execute command error: %s" % e)
        try:
            self.stdin = self.channel.makefile('wb', -1)
            self.stderr = map(string.strip, self.channel.makefile_stderr('rb', -1).readlines())
            self.stdout = map(string.strip, self.channel.makefile('rb', -1).readlines())
        except Exception as e:
            self.unknown("Get result error: %s" % e)
        try:
            self.status = self.channel.recv_exit_status()
        except paramiko.SSHException as e:
            self.unknown("Get return code error: %s" % e)
        else:
            if self.status != 0:
                self.unknown("Return code: %d , stderr: %s" % (self.status, self.errors))
            else:
                return self.stdout
        finally:
            self.logger.debug("Execute command finish.")

def
execute
(
self
,
command
,
timeout
=
)
:
try
:
self
.
channel
=
self
.
ssh
.
get_transport
(
)
.
open_session
(
)
except
paramiko
.
SSHException
as
e
:
self
.
unknown
(
"Create channel error: %s"
%
e
)
try
:
self
.
channel
.
settimeout
(
self
.
args
.
timeout
if
not
timeout
else
timeout
)
except
socket
.
timeout
as
e
:
self
.
unknown
(
"Settimeout for channel error: %s"
%
e
)
try
:
self
.
logger
.
debug
(
"command: {}"
.
format
(
command
)
)
self
.
channel
.
exec_command
(
command
)
except
paramiko
.
SSHException
as
e
:
self
.
unknown
(
"Execute command error: %s"
%
e
)
try
:
self
.
stdin
=
self
.
channel
.
makefile
(
'wb'
,
1
)
self
.
stderr
=
map
(
string
.
strip
,
self
.
channel
.
makefile_stderr
(
'rb'
,
1
)
.
readlines
(
)
)
self
.
stdout
=
map
(
string
.
strip
,
self
.
channel
.
makefile
(
'rb'
,
1
)
.
readlines
(
)
)
except
Exception
as
e
:
self
.
unknown
(
"Get result error: %s"
%
e
)
try
:
self
.
status
=
self
.
channel
.
recv_exit_status
(
)
except
paramiko
.
SSHException
as
e
:
self
.
unknown
(
"Get return code error: %s"
%
e
)
else
:
if
self
.
status
!=
0
:
self
.
unknown
(
"Return code: %d , stderr: %s"
%
(
self
.
status
,
self
.
errors
)
)
else
:
return
self
.
stdout
finally
:
self
.
logger
.
debug
(
"Execute command finish."
)


def slinky(filename, seconds_available, bucket_name, aws_key, aws_secret):
    """Simple program that creates an temp S3 link."""
    if not os.environ.get('AWS_ACCESS_KEY_ID') and os.environ.get('AWS_SECRET_ACCESS_KEY'):
    	print 'Need to set environment variables for AWS access and create a slinky bucket.'
    	exit()

    print create_temp_s3_link(filename, seconds_available, bucket_name)

Simple program that creates an temp S3 link .


def check_readable(self, timeout):
        """
        Poll ``self.stdout`` and return True if it is readable.

        :param float timeout: seconds to wait I/O
        :return: True if readable, else False
        :rtype: boolean
        """
        rlist, wlist, xlist = select.select([self._stdout], [], [], timeout)
        return bool(len(rlist))

def check_readable ( self , timeout ) : rlist , wlist , xlist = select . select ( [ self . _stdout ] , [ ] , [ ] , timeout ) return bool ( len ( rlist ) )

Poll self . stdout and return True if it is readable .


def get_indices_list(s: Any) -> List[str]:
    """ Retrieve a list of characters and escape codes where each escape
        code uses only one index. The indexes will not match up with the
        indexes in the original string.
    """
    indices = get_indices(s)
    return [
        indices[i] for i in sorted(indices, key=int)
    ]

def get_indices_list ( s : Any ) -> List [ str ] : indices = get_indices ( s ) return [ indices [ i ] for i in sorted ( indices , key = int ) ]

Retrieve a list of characters and escape codes where each escape code uses only one index . The indexes will not match up with the indexes in the original string .


def strip_codes(s: Any) -> str:
    """ Strip all color codes from a string.
        Returns empty string for "falsey" inputs.
    """
    return codepat.sub('', str(s) if (s or (s == 0)) else '')

def strip_codes ( s : Any ) -> str : return codepat . sub ( '' , str ( s ) if ( s or ( s == 0 ) ) else '' )

Strip all color codes from a string . Returns empty string for falsey inputs .


def init_build(self, asset, builder):
        """
        Called when builder group collect files
        Resolves absolute url if relative passed

        :type asset: static_bundle.builders.Asset
        :type builder: static_bundle.builders.StandardBuilder
        """
        if not self.abs_path:
            rel_path = utils.prepare_path(self.rel_bundle_path)
            self.abs_bundle_path = utils.prepare_path([builder.config.input_dir, rel_path])
            self.abs_path = True
        self.input_dir = builder.config.input_dir

def init_build ( self , asset , builder ) : if not self . abs_path : rel_path = utils . prepare_path ( self . rel_bundle_path ) self . abs_bundle_path = utils . prepare_path ( [ builder . config . input_dir , rel_path ] ) self . abs_path = True self . input_dir = builder . config . input_dir


def add_file(self, *args):
        """
        Add single file or list of files to bundle

        :type: file_path: str|unicode
        """
        for file_path in args:
            self.files.append(FilePath(file_path, self))

def add_file ( self , * args ) : for file_path in args : self . files . append ( FilePath ( file_path , self ) )


def add_directory(self, *args, **kwargs):
        """
        Add directory or directories list to bundle

        :param exclusions: List of excluded paths

        :type path: str|unicode
        :type exclusions: list
        """
        exc = kwargs.get('exclusions', None)
        for path in args:
            self.files.append(DirectoryPath(path, self, exclusions=exc))

def add_directory ( self , * args , * * kwargs ) : exc = kwargs . get ( 'exclusions' , None ) for path in args : self . files . append ( DirectoryPath ( path , self , exclusions = exc ) )


def add_path_object(self, *args):
        """
        Add custom path objects

        :type: path_object: static_bundle.paths.AbstractPath
        """
        for obj in args:
            obj.bundle = self
            self.files.append(obj)

def add_path_object ( self , * args ) : for obj in args : obj . bundle = self self . files . append ( obj )


def add_prepare_handler(self, prepare_handlers):
        """
        Add prepare handler to bundle

        :type: prepare_handler: static_bundle.handlers.AbstractPrepareHandler
        """
        if not isinstance(prepare_handlers, static_bundle.BUNDLE_ITERABLE_TYPES):
            prepare_handlers = [prepare_handlers]
        if self.prepare_handlers_chain is None:
            self.prepare_handlers_chain = []
        for handler in prepare_handlers:
            self.prepare_handlers_chain.append(handler)

def add_prepare_handler ( self , prepare_handlers ) : if not isinstance ( prepare_handlers , static_bundle . BUNDLE_ITERABLE_TYPES ) : prepare_handlers = [ prepare_handlers ] if self . prepare_handlers_chain is None : self . prepare_handlers_chain = [ ] for handler in prepare_handlers : self . prepare_handlers_chain . append ( handler )


def prepare(self):
        """
        Called when builder run collect files in builder group

        :rtype: list[static_bundle.files.StaticFileResult]
        """
        result_files = self.collect_files()
        chain = self.prepare_handlers_chain
        if chain is None:
            # default handlers
            chain = [
                LessCompilerPrepareHandler()
            ]
        for prepare_handler in chain:
            result_files = prepare_handler.prepare(result_files, self)
        return result_files

def
prepare
(
self
)
:
result_files
=
self
.
collect_files
(
)
chain
=
self
.
prepare_handlers_chain
if
chain
is
:
# default handlers
chain
=
[
LessCompilerPrepareHandler
(
)
]
for
prepare_handler
in
chain
:
result_files
=
prepare_handler
.
prepare
(
result_files
,
self
)
return
result_files


def filenumber_handle(self):
        """Get the number of files in the folder."""
        self.__results = []
        self.__dirs = []
        self.__files = []
        self.__ftp = self.connect()
        self.__ftp.dir(self.args.path, self.__results.append)
        self.logger.debug("dir results: {}".format(self.__results))
        self.quit()

        status = self.ok

        for data in self.__results:
            if "<DIR>" in data:
                self.__dirs.append(str(data.split()[3]))
            else:
                self.__files.append(str(data.split()[2]))

        self.__result = len(self.__files)
        self.logger.debug("result: {}".format(self.__result))

        # Compare the vlaue.
        if self.__result > self.args.warning:
            status = self.warning
        if self.__result > self.args.critical:
            status = self.critical

        # Output
        self.shortoutput = "Found {0} files in {1}.".format(self.__result,
                                                            self.args.path)
        [self.longoutput.append(line)
         for line in self.__results if self.__results]
        self.perfdata.append("{path}={result};{warn};{crit};0;".format(
            crit=self.args.critical,
            warn=self.args.warning,
            result=self.__result,
            path=self.args.path))

        self.logger.debug("Return status and output.")
        status(self.output())

def
filenumber_handle
(
self
)
:
self
.
__results
=
[
]
self
.
__dirs
=
[
]
self
.
__files
=
[
]
self
.
__ftp
=
self
.
connect
(
)
self
.
__ftp
.
dir
(
self
.
args
.
path
,
self
.
__results
.
append
)
self
.
logger
.
debug
(
"dir results: {}"
.
format
(
self
.
__results
)
)
self
.
quit
(
)
status
=
self
.
ok
for
data
in
self
.
__results
:
if
"<DIR>"
in
data
:
self
.
__dirs
.
append
(
str
(
data
.
split
(
)
[
3
]
)
)
else
:
self
.
__files
.
append
(
str
(
data
.
split
(
)
[
2
]
)
)
self
.
__result
=
len
(
self
.
__files
)
self
.
logger
.
debug
(
"result: {}"
.
format
(
self
.
__result
)
)
# Compare the vlaue.
if
self
.
__result
>
self
.
args
.
warning
:
status
=
self
.
warning
if
self
.
__result
>
self
.
args
.
critical
:
status
=
self
.
critical
# Output
self
.
shortoutput
=
"Found {0} files in {1}."
.
format
(
self
.
__result
,
self
.
args
.
path
)
[
self
.
longoutput
.
append
(
line
)
for
line
in
self
.
__results
if
self
.
__results
]
self
.
perfdata
.
append
(
"{path}={result};{warn};{crit};0;"
.
format
(
crit
=
self
.
args
.
critical
,
warn
=
self
.
args
.
warning
,
result
=
self
.
__result
,
path
=
self
.
args
.
path
)
)
self
.
logger
.
debug
(
"Return status and output."
)
status
(
self
.
output
(
)
)


def register_json(self, data):
        """
        Register the contents as JSON
        """
        j = json.loads(data)
        self.last_data_timestamp = \
                datetime.datetime.utcnow().replace(microsecond=0).isoformat()
        try:
            for v in j:
                # prepare the sensor entry container
                self.data[v[self.id_key]] = {}
                # add the mandatory entries
                self.data[v[self.id_key]][self.id_key] = \
                                            v[self.id_key]
                self.data[v[self.id_key]][self.value_key] = \
                                            v[self.value_key]
                # add the optional well known entries if provided
                if self.unit_key in v:
                    self.data[v[self.id_key]][self.unit_key] = \
                                            v[self.unit_key]
                if self.threshold_key in v:
                    self.data[v[self.id_key]][self.threshold_key] = \
                                            v[self.threshold_key]
                # add any further entries found
                for k in self.other_keys:
                    if k in v:
                        self.data[v[self.id_key]][k] = v[k]
                # add the custom sensor time
                if self.sensor_time_key in v:
                    self.data[v[self.sensor_time_key]][self.sensor_time_key] = \
                                            v[self.sensor_time_key]
                # last: add the time the data was received (overwriting any
                # not properly defined timestamp that was already there)
                self.data[v[self.id_key]][self.time_key] = \
                                            self.last_data_timestamp
        except KeyError as e:
            print("The main key was not found on the serial input line: " + \
                    str(e))
        except ValueError as e:
            print("No valid JSON string received. Waiting for the next turn.")
            print("The error was: " + str(e))


def get_translated_data(self):
        """
        Translate the data with the translation table
        """
        j = {}
        for k in self.data:
            d = {}
            for l in self.data[k]:
                d[self.translation_keys[l]] = self.data[k][l]
            j[k] = d
        return j

def get_translated_data ( self ) : j = { } for k in self . data : d = { } for l in self . data [ k ] : d [ self . translation_keys [ l ] ] = self . data [ k ] [ l ] j [ k ] = d return j


def get_json(self, prettyprint=False, translate=True):
        """
        Get the data in JSON form
        """
        j = []
        if translate:
            d = self.get_translated_data()
        else:
            d = self.data
        for k in d:
            j.append(d[k])
        if prettyprint:
            j = json.dumps(j, indent=2, separators=(',',': '))
        else:
            j = json.dumps(j)
        return j

def
get_json
(
self
,
prettyprint
=
False
,
translate
=
True
)
:
j
=
[
]
if
translate
:
d
=
self
.
get_translated_data
(
)
else
:
d
=
self
.
data
for
k
in
d
:
j
.
append
(
d
[
k
]
)
if
prettyprint
:
j
=
json
.
dumps
(
j
,
indent
=
2
,
separators
=
(
','
,
': '
)
)
else
:
j
=
json
.
dumps
(
j
)
return
j


def get_json_tuples(self, prettyprint=False, translate=True):
        """
        Get the data as JSON tuples
        """
        j = self.get_json(prettyprint, translate)
        if len(j) > 2:
            if prettyprint:
                j = j[1:-2] + ",\n"
            else:
                j = j[1:-1] + ","
        else:
            j = ""
        return j

def get_json_tuples ( self , prettyprint = False , translate = True ) : j = self . get_json ( prettyprint , translate ) if len ( j ) > 2 : if prettyprint : j = j [ 1 : - 2 ] + ",\n" else : j = j [ 1 : - 1 ] + "," else : j = "" return j


def get(self, url, params={}):
        """
        Issues a GET request against the API, properly formatting the params

        :param url: a string, the url you are requesting
        :param params: a dict, the key-value of all the paramaters needed
                       in the request
        :returns: a dict parsed of the JSON response
        """

        params.update({'api_key': self.api_key})
        try:
            response = requests.get(self.host + url, params=params)
        except RequestException as e:
            response = e.args

        return self.json_parse(response.content)

def get ( self , url , params = { } ) : params . update ( { 'api_key' : self . api_key } ) try : response = requests . get ( self . host + url , params = params ) except RequestException as e : response = e . args return self . json_parse ( response . content )

Issues a GET request against the API properly formatting the params


def post(self, url, params={}, files=None):
        """
        Issues a POST request against the API, allows for multipart data uploads

        :param url: a string, the url you are requesting
        :param params: a dict, the key-value of all the parameters needed
                       in the request
        :param files: a list, the list of tuples of files

        :returns: a dict parsed of the JSON response
        """
        params.update({'api_key': self.api_key})
        try:
            response = requests.post(self.host + url, data=params, files=files)
            return self.json_parse(response.content)
        except RequestException as e:
            return self.json_parse(e.args)

def post ( self , url , params = { } , files = None ) : params . update ( { 'api_key' : self . api_key } ) try : response = requests . post ( self . host + url , data = params , files = files ) return self . json_parse ( response . content ) except RequestException as e : return self . json_parse ( e . args )

Issues a POST request against the API allows for multipart data uploads


def load_values(self):
        """
        Go through the env var map, transferring the values to this object
        as attributes.

        :raises: RuntimeError if a required env var isn't defined.
        """

        for config_name, evar in self.evar_defs.items():
            if evar.is_required and evar.name not in os.environ:
                raise RuntimeError((
                    "Missing required environment variable: {evar_name}\n"
                    "{help_txt}"
                ).format(evar_name=evar.name, help_txt=evar.help_txt))
            # Env var is present. Transfer its value over.
            if evar.name in os.environ:
                self[config_name] = os.environ.get(evar.name)
            else:
                self[config_name] = evar.default_val
            # Perform any validations or transformations.
            for filter in evar.filters:
                current_val = self.get(config_name)
                new_val = filter(current_val, evar)
                self[config_name] = new_val
        # This is the top-level filter that is often useful for checking
        # the values of related env vars (instead of individual validation).
        self._filter_all()

Go through the env var map transferring the values to this object as attributes .


def embed_data(request):
    """
    Create a temporary directory with input data for the test.
    The directory contents is copied from a directory with the same name as the module located in the same directory of
    the test module.
    """
    result = _EmbedDataFixture(request)
    result.delete_data_dir()
    result.create_data_dir()
    yield result
    result.delete_data_dir()

def embed_data ( request ) : result = _EmbedDataFixture ( request ) result . delete_data_dir ( ) result . create_data_dir ( ) yield result result . delete_data_dir ( )

Create a temporary directory with input data for the test . The directory contents is copied from a directory with the same name as the module located in the same directory of the test module .


def assert_equal_files(self, obtained_fn, expected_fn, fix_callback=lambda x:x, binary=False, encoding=None):
        '''
        Compare two files contents. If the files differ, show the diff and write a nice HTML
        diff file into the data directory.

        Searches for the filenames both inside and outside the data directory (in that order).

        :param unicode obtained_fn: basename to obtained file into the data directory, or full path.

        :param unicode expected_fn: basename to expected file into the data directory, or full path.

        :param bool binary:
            Thread both files as binary files.

        :param unicode encoding:
            File's encoding. If not None, contents obtained from file will be decoded using this
            `encoding`.

        :param callable fix_callback:
            A callback to "fix" the contents of the obtained (first) file.
            This callback receives a list of strings (lines) and must also return a list of lines,
            changed as needed.
            The resulting lines will be used to compare with the contents of expected_fn.

        :param bool binary:
            .. seealso:: zerotk.easyfs.GetFileContents
        '''
        import os
        from zerotk.easyfs import GetFileContents, GetFileLines

        __tracebackhide__ = True
        import io

        def FindFile(filename):
            # See if this path exists in the data dir
            data_filename = self.get_filename(filename)
            if os.path.isfile(data_filename):
                return data_filename

            # If not, we might have already received a full path
            if os.path.isfile(filename):
                return filename

            # If we didn't find anything, raise an error
            from ._exceptions import MultipleFilesNotFound
            raise MultipleFilesNotFound([filename, data_filename])

        obtained_fn = FindFile(obtained_fn)
        expected_fn = FindFile(expected_fn)

        if binary:
            obtained_lines = GetFileContents(obtained_fn, binary=True)
            expected_lines = GetFileContents(expected_fn, binary=True)
            assert obtained_lines == expected_lines
        else:
            obtained_lines = fix_callback(GetFileLines(obtained_fn, encoding=encoding))
            expected_lines = GetFileLines(expected_fn, encoding=encoding)

            if obtained_lines != expected_lines:
                html_fn = os.path.splitext(obtained_fn)[0] + '.diff.html'
                html_diff = self._generate_html_diff(
                    expected_fn, expected_lines, obtained_fn, obtained_lines)
                with io.open(html_fn, 'w') as f:
                    f.write(html_diff)

                import difflib
                diff = ['FILES DIFFER:', obtained_fn, expected_fn]
                diff += ['HTML DIFF: %s' % html_fn]
                diff += difflib.context_diff(obtained_lines, expected_lines)
                raise AssertionError('\n'.join(diff) + '\n')

Compare two files contents . If the files differ show the diff and write a nice HTML diff file into the data directory .


def _generate_html_diff(self, expected_fn, expected_lines, obtained_fn, obtained_lines):
        """
        Returns a nice side-by-side diff of the given files, as a string.

        """
        import difflib
        differ = difflib.HtmlDiff()
        return differ.make_file(
            fromlines=expected_lines,
            fromdesc=expected_fn,
            tolines=obtained_lines,
            todesc=obtained_fn,
        )

def _generate_html_diff ( self , expected_fn , expected_lines , obtained_fn , obtained_lines ) : import difflib differ = difflib . HtmlDiff ( ) return differ . make_file ( fromlines = expected_lines , fromdesc = expected_fn , tolines = obtained_lines , todesc = obtained_fn , )

Returns a nice side - by - side diff of the given files as a string .


def add_peer(self, peer):
        """
        Add a peer or multiple peers to the PEERS variable, takes a single string or a list.

        :param peer(list or string)
        """
        if type(peer) == list:
            for i in peer:
                check_url(i)
            self.PEERS.extend(peer)
        elif type(peer) == str:
            check_url(peer)
            self.PEERS.append(peer)

def add_peer ( self , peer ) : if type ( peer ) == list : for i in peer : check_url ( i ) self . PEERS . extend ( peer ) elif type ( peer ) == str : check_url ( peer ) self . PEERS . append ( peer )

Add a peer or multiple peers to the PEERS variable takes a single string or a list .


def remove_peer(self, peer):
        """
        remove one or multiple peers from PEERS variable

        :param peer(list or string):
        """
        if type(peer) == list:
            for x in peer:
                check_url(x)
                for i in self.PEERS:
                    if x in i:
                        self.PEERS.remove(i)
        elif type(peer) == str:
            check_url(peer)
            for i in self.PEERS:
                if peer == i:
                    self.PEERS.remove(i)
        else:
            raise ValueError('peer paramater did not pass url validation')


def status(self):
        """
        check the status of the network and the peers

        :return: network_height, peer_status
        """
        peer = random.choice(self.PEERS)
        formatted_peer = 'http://{}:4001'.format(peer)
        peerdata = requests.get(url=formatted_peer + '/api/peers/').json()['peers']
        peers_status = {}

        networkheight = max([x['height'] for x in peerdata])

        for i in peerdata:
            if 'http://{}:4001'.format(i['ip']) in self.PEERS:
                peers_status.update({i['ip']: {
                    'height': i['height'],
                    'status': i['status'],
                    'version': i['version'],
                    'delay': i['delay'],
                }})

        return {
            'network_height': networkheight,
            'peer_status': peers_status
        }

def status ( self ) : peer = random . choice ( self . PEERS ) formatted_peer = 'http://{}:4001' . format ( peer ) peerdata = requests . get ( url = formatted_peer + '/api/peers/' ) . json ( ) [ 'peers' ] peers_status = { } networkheight = max ( [ x [ 'height' ] for x in peerdata ] ) for i in peerdata : if 'http://{}:4001' . format ( i [ 'ip' ] ) in self . PEERS : peers_status . update ( { i [ 'ip' ] : { 'height' : i [ 'height' ] , 'status' : i [ 'status' ] , 'version' : i [ 'version' ] , 'delay' : i [ 'delay' ] , } } ) return { 'network_height' : networkheight , 'peer_status' : peers_status }


def broadcast_tx(self, address, amount, secret, secondsecret=None, vendorfield=''):
        """broadcasts a transaction to the peerslist using ark-js library"""

        peer = random.choice(self.PEERS)
        park = Park(
            peer,
            4001,
            constants.ARK_NETHASH,
            '1.1.1'
        )

        return park.transactions().create(address, str(amount), vendorfield, secret, secondsecret)

def broadcast_tx ( self , address , amount , secret , secondsecret = None , vendorfield = '' ) : peer = random . choice ( self . PEERS ) park = Park ( peer , 4001 , constants . ARK_NETHASH , '1.1.1' ) return park . transactions ( ) . create ( address , str ( amount ) , vendorfield , secret , secondsecret )

broadcasts a transaction to the peerslist using ark - js library


def register(self, service, name=''):
        """
        Exposes a given service to this API.
        """
        try:
            is_model = issubclass(service, orb.Model)
        except StandardError:
            is_model = False

        # expose an ORB table dynamically as a service
        if is_model:
            self.services[service.schema().dbname()] = (ModelService, service)

        else:
            super(OrbApiFactory, self).register(service, name=name)


def main():
    """ Main entry point, expects doctopt arg dict as argd. """
    global DEBUG
    argd = docopt(USAGESTR, version=VERSIONSTR, script=SCRIPT)
    DEBUG = argd['--debug']

    width = parse_int(argd['--width'] or DEFAULT_WIDTH) or 1
    indent = parse_int(argd['--indent'] or (argd['--INDENT'] or 0))
    prepend = ' ' * (indent * 4)
    if prepend and argd['--indent']:
        # Smart indent, change max width based on indention.
        width -= len(prepend)

    userprepend = argd['--prepend'] or (argd['--PREPEND'] or '')
    prepend = ''.join((prepend, userprepend))
    if argd['--prepend']:
        # Smart indent, change max width based on prepended text.
        width -= len(userprepend)
    userappend = argd['--append'] or (argd['--APPEND'] or '')
    if argd['--append']:
        width -= len(userappend)

    if argd['WORDS']:
        # Try each argument as a file name.
        argd['WORDS'] = (
            (try_read_file(w) if len(w) < 256 else w)
            for w in argd['WORDS']
        )
        words = ' '.join((w for w in argd['WORDS'] if w))
    else:
        # No text/filenames provided, use stdin for input.
        words = read_stdin()

    block = FormatBlock(words).iter_format_block(
        chars=argd['--chars'],
        fill=argd['--fill'],
        prepend=prepend,
        strip_first=argd['--stripfirst'],
        append=userappend,
        strip_last=argd['--striplast'],
        width=width,
        newlines=argd['--newlines'],
        lstrip=argd['--lstrip'],
    )

    for i, line in enumerate(block):
        if argd['--enumerate']:
            # Current line number format supports up to 999 lines before
            # messing up. Who would format 1000 lines like this anyway?
            print('{: >3}: {}'.format(i + 1, line))
        else:
            print(line)

    return 0

Main entry point expects doctopt arg dict as argd .


def debug(*args, **kwargs):
    """ Print a message only if DEBUG is truthy. """
    if not (DEBUG and args):
        return None

    # Include parent class name when given.
    parent = kwargs.get('parent', None)
    with suppress(KeyError):
        kwargs.pop('parent')

    # Go back more than once when given.
    backlevel = kwargs.get('back', 1)
    with suppress(KeyError):
        kwargs.pop('back')

    frame = inspect.currentframe()
    # Go back a number of frames (usually 1).
    while backlevel > 0:
        frame = frame.f_back
        backlevel -= 1
    fname = os.path.split(frame.f_code.co_filename)[-1]
    lineno = frame.f_lineno
    if parent:
        func = '{}.{}'.format(parent.__class__.__name__, frame.f_code.co_name)
    else:
        func = frame.f_code.co_name

    lineinfo = '{}:{} {}: '.format(
        C(fname, 'yellow'),
        C(str(lineno).ljust(4), 'blue'),
        C().join(C(func, 'magenta'), '()').ljust(20)
    )
    # Patch args to stay compatible with print().
    pargs = list(C(a, 'green').str() for a in args)
    pargs[0] = ''.join((lineinfo, pargs[0]))
    print_err(*pargs, **kwargs)

Print a message only if DEBUG is truthy .


def parse_int(s):
    """ Parse a string as an integer.
        Exit with a message on failure.
    """
    try:
        val = int(s)
    except ValueError:
        print_err('\nInvalid integer: {}'.format(s))
        sys.exit(1)
    return val

def
parse_int
(
s
)
:
try
:
val
=
int
(
s
)
except
ValueError
:
print_err
(
'\nInvalid integer: {}'
.
format
(
s
)
)
sys
.
exit
(
1
)
return
val

Parse a string as an integer . Exit with a message on failure .


def try_read_file(s):
    """ If `s` is a file name, read the file and return it's content.
        Otherwise, return the original string.
        Returns None if the file was opened, but errored during reading.
    """
    try:
        with open(s, 'r') as f:
            data = f.read()
    except FileNotFoundError:
        # Not a file name.
        return s
    except EnvironmentError as ex:
        print_err('\nFailed to read file: {}\n  {}'.format(s, ex))
        return None
    return data

def
try_read_file
(
s
)
:
try
:
with
open
(
s
,
'r'
)
as
f
:
data
=
f
.
read
(
)
except
FileNotFoundError
:
# Not a file name.
return
s
except
EnvironmentError
as
ex
:
print_err
(
'\nFailed to read file: {}\n  {}'
.
format
(
s
,
ex
)
)
return
return
data

If s is a file name read the file and return it s content . Otherwise return the original string . Returns None if the file was opened but errored during reading .


def wait(self, timeout=None):
        """
        Wait for response until timeout.
        If timeout is specified to None, ``self.timeout`` is used.

        :param float timeout: seconds to wait I/O
        """
        if timeout is None:
            timeout = self._timeout
        while self._process.check_readable(timeout):
            self._flush()

def wait ( self , timeout = None ) : if timeout is None : timeout = self . _timeout while self . _process . check_readable ( timeout ) : self . _flush ( )

Wait for response until timeout . If timeout is specified to None self . timeout is used .


def make_seekable(fileobj):
    """
    If the file-object is not seekable, return  ArchiveTemp of the fileobject,
    otherwise return the file-object itself
    """
    if sys.version_info < (3, 0) and isinstance(fileobj, file):
        filename = fileobj.name
        fileobj = io.FileIO(fileobj.fileno(), closefd=False)
        fileobj.name = filename
    assert isinstance(fileobj, io.IOBase), \
        "fileobj must be an instance of io.IOBase or a file, got %s" \
        % type(fileobj)
    return fileobj if fileobj.seekable() \
        else ArchiveTemp(fileobj)

If the file - object is not seekable return ArchiveTemp of the fileobject otherwise return the file - object itself


def init_app(self, app):
        """Setup before_request, after_request handlers for tracing.
        """
        app.config.setdefault("TRACY_REQUIRE_CLIENT", False)
        if not hasattr(app, 'extensions'):
            app.extensions = {}

        app.extensions['restpoints'] = self
        app.before_request(self._before)
        app.after_request(self._after)

def init_app ( self , app ) : app . config . setdefault ( "TRACY_REQUIRE_CLIENT" , False ) if not hasattr ( app , 'extensions' ) : app . extensions = { } app . extensions [ 'restpoints' ] = self app . before_request ( self . _before ) app . after_request ( self . _after )

Setup before_request after_request handlers for tracing .


def _before(self):
        """Records the starting time of this reqeust.
        """
        # Don't trace excluded routes.
        if request.path in self.excluded_routes:
            request._tracy_exclude = True
            return

        request._tracy_start_time = monotonic()
        client = request.headers.get(trace_header_client, None)
        require_client = current_app.config.get("TRACY_REQUIRE_CLIENT", False)
        if client is None and require_client:
            abort(400, "Missing %s header" % trace_header_client)

        request._tracy_client = client
        request._tracy_id = request.headers.get(trace_header_id, new_id())

def
_before
(
self
)
:
# Don't trace excluded routes.
if
request
.
path
in
self
.
excluded_routes
:
request
.
_tracy_exclude
=
True
return
request
.
_tracy_start_time
=
monotonic
(
)
client
=
request
.
headers
.
get
(
trace_header_client
,
)
require_client
=
current_app
.
config
.
get
(
"TRACY_REQUIRE_CLIENT"
,
False
)
if
client
is
and
require_client
:
abort
(
400
,
"Missing %s header"
%
trace_header_client
)
request
.
_tracy_client
=
client
request
.
_tracy_id
=
request
.
headers
.
get
(
trace_header_id
,
new_id
(
)
)

Records the starting time of this reqeust .


def _after(self, response):
        """Calculates the request duration, and adds a transaction
        ID to the header.
        """
        # Ignore excluded routes.
        if getattr(request, '_tracy_exclude', False):
            return response

        duration = None
        if getattr(request, '_tracy_start_time', None):
            duration = monotonic() - request._tracy_start_time

        # Add Trace_ID header.
        trace_id = None
        if getattr(request, '_tracy_id', None):
            trace_id = request._tracy_id
            response.headers[trace_header_id] = trace_id

        # Get the invoking client.
        trace_client = None
        if getattr(request, '_tracy_client', None):
            trace_client = request._tracy_client

        # Extra log kwargs.
        d = {'status_code': response.status_code,
             'url': request.base_url,
             'client_ip': request.remote_addr,
             'trace_name': trace_client,
             'trace_id': trace_id,
             'trace_duration': duration}
        logger.info(None, extra=d)
        return response

def
_after
(
self
,
response
)
:
# Ignore excluded routes.
if
getattr
(
request
,
'_tracy_exclude'
,
False
)
:
return
response
duration
=
if
getattr
(
request
,
'_tracy_start_time'
,
)
:
duration
=
monotonic
(
)
request
.
_tracy_start_time
# Add Trace_ID header.
trace_id
=
if
getattr
(
request
,
'_tracy_id'
,
)
:
trace_id
=
request
.
_tracy_id
response
.
headers
[
trace_header_id
]
=
trace_id
# Get the invoking client.
trace_client
=
if
getattr
(
request
,
'_tracy_client'
,
)
:
trace_client
=
request
.
_tracy_client
# Extra log kwargs.
d
=
{
'status_code'
:
response
.
status_code
,
'url'
:
request
.
base_url
,
'client_ip'
:
request
.
remote_addr
,
'trace_name'
:
trace_client
,
'trace_id'
:
trace_id
,
'trace_duration'
:
duration
}
logger
.
info
(
,
extra
=
d
)
return
response

Calculates the request duration and adds a transaction ID to the header .


def expand_words(self, line, width=60):
        """ Insert spaces between words until it is wide enough for `width`.
        """
        if not line.strip():
            return line
        # Word index, which word to insert on (cycles between 1->len(words))
        wordi = 1
        while len(strip_codes(line)) < width:
            wordendi = self.find_word_end(line, wordi)
            if wordendi < 0:
                # Reached the end?, try starting at the front again.
                wordi = 1
                wordendi = self.find_word_end(line, wordi)
            if wordendi < 0:
                # There are no spaces to expand, just prepend one.
                line = ''.join((' ', line))
            else:
                line = ' '.join((line[:wordendi], line[wordendi:]))
                wordi += 1

        # Don't push a single word all the way to the right.
        if ' ' not in strip_codes(line).strip():
            return line.replace(' ', '')
        return line

Insert spaces between words until it is wide enough for width .


def iter_add_text(self, lines, prepend=None, append=None):
        """ Prepend or append text to lines. Yields each line. """
        if (prepend is None) and (append is None):
            yield from lines
        else:
            # Build up a format string, with optional {prepend}/{append}
            fmtpcs = ['{prepend}'] if prepend else []
            fmtpcs.append('{line}')
            if append:
                fmtpcs.append('{append}')
            fmtstr = ''.join(fmtpcs)
            yield from (
                fmtstr.format(prepend=prepend, line=line, append=append)
                for line in lines
            )

Prepend or append text to lines . Yields each line .


def iter_char_block(self, text=None, width=60, fmtfunc=str):
        """ Format block by splitting on individual characters. """
        if width < 1:
            width = 1
        text = (self.text if text is None else text) or ''
        text = ' '.join(text.split('\n'))
        escapecodes = get_codes(text)
        if not escapecodes:
            # No escape codes, use simple method.
            yield from (
                fmtfunc(text[i:i + width])
                for i in range(0, len(text), width)
            )
        else:
            # Ignore escape codes when counting.
            blockwidth = 0
            block = []
            for i, s in enumerate(get_indices_list(text)):
                block.append(s)
                if len(s) == 1:
                    # Normal char.
                    blockwidth += 1
                if blockwidth == width:
                    yield ''.join(block)
                    block = []
                    blockwidth = 0
            if block:
                yield ''.join(block)

def
iter_char_block
(
self
,
text
=
,
width
=
60
,
fmtfunc
=
str
)
:
if
width
<
1
:
width
=
1
text
=
(
self
.
text
if
text
is
else
text
)
or
''
text
=
' '
.
join
(
text
.
split
(
'\n'
)
)
escapecodes
=
get_codes
(
text
)
if
not
escapecodes
:
# No escape codes, use simple method.
yield
from
(
fmtfunc
(
text
[
i
:
i
+
width
]
)
for
i
in
range
(
0
,
len
(
text
)
,
width
)
)
else
:
# Ignore escape codes when counting.
blockwidth
=
0
block
=
[
]
for
i
,
s
in
enumerate
(
get_indices_list
(
text
)
)
:
block
.
append
(
s
)
if
len
(
s
)
==
1
:
# Normal char.
blockwidth
+=
1
if
blockwidth
==
width
:
yield
''
.
join
(
block
)
block
=
[
]
blockwidth
=
0
if
block
:
yield
''
.
join
(
block
)

Format block by splitting on individual characters .


def iter_space_block(self, text=None, width=60, fmtfunc=str):
        """ Format block by wrapping on spaces. """
        if width < 1:
            width = 1
        curline = ''
        text = (self.text if text is None else text) or ''
        for word in text.split():
            possibleline = ' '.join((curline, word)) if curline else word
            # Ignore escape codes.
            codelen = sum(len(s) for s in get_codes(possibleline))
            reallen = len(possibleline) - codelen
            if reallen > width:
                # This word would exceed the limit, start a new line with
                # it.
                yield fmtfunc(curline)
                curline = word
            else:
                curline = possibleline
        # yield the last line.
        if curline:
            yield fmtfunc(curline)


def squeeze_words(line, width=60):
        """ Remove spaces in between words until it is small enough for
            `width`.
            This will always leave at least one space between words,
            so it may not be able to get below `width` characters.
        """
        # Start removing spaces to "squeeze" the text, leaving at least one.
        while ('  ' in line) and (len(line) > width):
            # Remove two spaces from the end, replace with one.
            head, _, tail = line.rpartition('  ')
            line = ' '.join((head, tail))
        return line

Remove spaces in between words until it is small enough for width . This will always leave at least one space between words so it may not be able to get below width characters .


def check_ip(self, ip):
        """
        Check IP trough the httpBL API

        :param ip: ipv4 ip address
        :return: httpBL results or None if any error is occurred
        """

        self._last_result = None

        if is_valid_ipv4(ip):
            key = None
            if self._use_cache:
                key = self._make_cache_key(ip)
                self._last_result = self._cache.get(key, version=self._cache_version)

            if self._last_result is None:
                # request httpBL API
                error, age, threat, type = self._request_httpbl(ip)
                if error == 127 or error == 0:
                    self._last_result = {
                        'error': error,
                        'age': age,
                        'threat': threat,
                        'type': type
                    }
                    if self._use_cache:
                        self._cache.set(key, self._last_result, timeout=self._api_timeout, version=self._cache_version)
            if self._last_result is not None and settings.CACHED_HTTPBL_USE_LOGGING:
                logger.info(
                    'httpBL check ip: {0}; '
                    'httpBL result: error: {1}, age: {2}, threat: {3}, type: {4}'.format(ip,
                                                                                self._last_result['error'],
                                                                                self._last_result['age'],
                                                                                self._last_result['threat'],
                                                                                self._last_result['type']
                                                                                )
                )

        return self._last_result


def is_threat(self, result=None, harmless_age=None, threat_score=None, threat_type=None):
        """
        Check if IP is a threat

        :param result: httpBL results; if None, then results from last check_ip() used (optional)
        :param harmless_age: harmless age for check if httpBL age is older (optional)
        :param threat_score: threat score for check if httpBL threat is lower (optional)
        :param threat_type:  threat type, if not equal httpBL score type, then return False (optional)
        :return: True or False
        """

        harmless_age = harmless_age if harmless_age is not None else settings.CACHED_HTTPBL_HARMLESS_AGE
        threat_score = threat_score if threat_score is not None else settings.CACHED_HTTPBL_THREAT_SCORE
        threat_type = threat_type if threat_type is not None else -1
        result = result if result is not None else self._last_result
        threat = False
        if result is not None:
            if result['age'] < harmless_age and result['threat'] > threat_score:
                threat = True
            if threat_type > -1:
                if result['type'] & threat_type:
                    threat = True
                else:
                    threat = False
        return threat

def is_threat ( self , result = None , harmless_age = None , threat_score = None , threat_type = None ) : harmless_age = harmless_age if harmless_age is not None else settings . CACHED_HTTPBL_HARMLESS_AGE threat_score = threat_score if threat_score is not None else settings . CACHED_HTTPBL_THREAT_SCORE threat_type = threat_type if threat_type is not None else - 1 result = result if result is not None else self . _last_result threat = False if result is not None : if result [ 'age' ] < harmless_age and result [ 'threat' ] > threat_score : threat = True if threat_type > - 1 : if result [ 'type' ] & threat_type : threat = True else : threat = False return threat


def is_suspicious(self, result=None):
        """
        Check if IP is suspicious

        :param result: httpBL results; if None, then results from last check_ip() used (optional)
        :return: True or False
        """

        result = result if result is not None else self._last_result
        suspicious = False
        if result is not None:
            suspicious = True if result['type'] > 0 else False
        return suspicious

def is_suspicious ( self , result = None ) : result = result if result is not None else self . _last_result suspicious = False if result is not None : suspicious = True if result [ 'type' ] > 0 else False return suspicious


def invalidate_ip(self, ip):
        """
        Invalidate httpBL cache for IP address

        :param ip: ipv4 IP address
        """

        if self._use_cache:
            key = self._make_cache_key(ip)
            self._cache.delete(key, version=self._cache_version)

def invalidate_ip ( self , ip ) : if self . _use_cache : key = self . _make_cache_key ( ip ) self . _cache . delete ( key , version = self . _cache_version )


def invalidate_cache(self):
        """
        Invalidate httpBL cache
        """

        if self._use_cache:
            self._cache_version += 1
            self._cache.increment('cached_httpbl_{0}_version'.format(self._api_key))

def invalidate_cache ( self ) : if self . _use_cache : self . _cache_version += 1 self . _cache . increment ( 'cached_httpbl_{0}_version' . format ( self . _api_key ) )


def run(self):
        """Runs the consumer."""
        self.log.debug('consumer is running...')

        self.running = True
        while self.running:
            self.upload()

        self.log.debug('consumer exited.')

def
run
(
self
)
:
self
.
log
.
debug
(
'consumer is running...'
)
self
.
running
=
True
while
self
.
running
:
self
.
upload
(
)
self
.
log
.
debug
(
'consumer exited.'
)


def upload(self):
        """Upload the next batch of items, return whether successful."""
        success = False
        batch = self.next()
        if len(batch) == 0:
            return False

        try:
            self.request(batch)
            success = True
        except Exception as e:
            self.log.error('error uploading: %s', e)
            success = False
            if self.on_error:
                self.on_error(e, batch)
        finally:
            # cleanup
            for item in batch:
                self.queue.task_done()

            return success

def
upload
(
self
)
:
success
=
False
batch
=
self
.
next
(
)
if
len
(
batch
)
==
0
:
return
False
try
:
self
.
request
(
batch
)
success
=
True
except
Exception
as
e
:
self
.
log
.
error
(
'error uploading: %s'
,
e
)
success
=
False
if
self
.
on_error
:
self
.
on_error
(
e
,
batch
)
finally
:
# cleanup
for
item
in
batch
:
self
.
queue
.
task_done
(
)
return
success

Upload the next batch of items return whether successful .


def next(self):
        """Return the next batch of items to upload."""
        queue = self.queue
        items = []
        item = self.next_item()
        if item is None:
            return items

        items.append(item)
        while len(items) < self.upload_size and not queue.empty():
            item = self.next_item()
            if item:
                items.append(item)

        return items

def next ( self ) : queue = self . queue items = [ ] item = self . next_item ( ) if item is None : return items items . append ( item ) while len ( items ) < self . upload_size and not queue . empty ( ) : item = self . next_item ( ) if item : items . append ( item ) return items

Return the next batch of items to upload .


def next_item(self):
        """Get a single item from the queue."""
        queue = self.queue
        try:
            item = queue.get(block=True, timeout=5)
            return item
        except Exception:
            return None

def next_item ( self ) : queue = self . queue try : item = queue . get ( block = True , timeout = 5 ) return item except Exception : return None


def request(self, batch, attempt=0):
        """Attempt to upload the batch and retry before raising an error """
        try:
            q = self.api.new_queue()
            for msg in batch:
                q.add(msg['event'], msg['value'], source=msg['source'])
            q.submit()
        except:
            if attempt > self.retries:
                raise
            self.request(batch, attempt+1)

def request ( self , batch , attempt = 0 ) : try : q = self . api . new_queue ( ) for msg in batch : q . add ( msg [ 'event' ] , msg [ 'value' ] , source = msg [ 'source' ] ) q . submit ( ) except : if attempt > self . retries : raise self . request ( batch , attempt + 1 )


def _camelcase_to_underscore(url):
    """
    Translate camelCase into underscore format.

    >>> _camelcase_to_underscore('minutesBetweenSummaries')
    'minutes_between_summaries'

    """
    def upper2underscore(text):
        for char in text:
            if char.islower():
                yield char
            else:
                yield '_'
                if char.isalpha():
                    yield char.lower()
    return ''.join(upper2underscore(url))

def _camelcase_to_underscore ( url ) : def upper2underscore ( text ) : for char in text : if char . islower ( ) : yield char else : yield '_' if char . isalpha ( ) : yield char . lower ( ) return '' . join ( upper2underscore ( url ) )

Translate camelCase into underscore format .


def create_tree(endpoints):
    """
    Creates the Trello endpoint tree.

    >>> r = {'1': { \
                 'actions': {'METHODS': {'GET'}}, \
                 'boards': { \
                     'members': {'METHODS': {'DELETE'}}}} \
            }
    >>> r == create_tree([ \
                 'GET /1/actions/[idAction]', \
                 'DELETE /1/boards/[board_id]/members/[idMember]'])
    True

    """
    tree = {}

    for method, url, doc in endpoints:
        path = [p for p in url.strip('/').split('/')]
        here = tree

        # First element (API Version).
        version = path[0]
        here.setdefault(version, {})
        here = here[version]

        # The rest of elements of the URL.
        for p in path[1:]:
            part = _camelcase_to_underscore(p)
            here.setdefault(part, {})
            here = here[part]

        # Allowed HTTP methods.
        if not 'METHODS' in here:
            here['METHODS'] = [[method, doc]]
        else:
            if not method in here['METHODS']:
                here['METHODS'].append([method, doc])

    return tree

def
create_tree
(
endpoints
)
:
tree
=
{
}
for
method
,
url
,
doc
in
endpoints
:
path
=
[
p
for
p
in
url
.
strip
(
'/'
)
.
split
(
'/'
)
]
here
=
tree
# First element (API Version).
version
=
path
[
0
]
here
.
setdefault
(
version
,
{
}
)
here
=
here
[
version
]
# The rest of elements of the URL.
for
p
in
path
[
1
:
]
:
part
=
_camelcase_to_underscore
(
p
)
here
.
setdefault
(
part
,
{
}
)
here
=
here
[
part
]
# Allowed HTTP methods.
if
not
'METHODS'
in
here
:
here
[
'METHODS'
]
=
[
[
method
,
doc
]
]
else
:
if
not
method
in
here
[
'METHODS'
]
:
here
[
'METHODS'
]
.
append
(
[
method
,
doc
]
)
return
tree