def synchronize(self, func=None, wait=None, errors=()):
        """
        This method is Capybara's primary defense against asynchronicity problems. It works by
        attempting to run a given decorated function until it succeeds. The exact behavior of this
        method depends on a number of factors. Basically there are certain exceptions which, when
        raised from the decorated function, instead of bubbling up, are caught, and the function is
        re-run.

        Certain drivers have no support for asynchronous processes. These drivers run the function,
        and any error raised bubbles up immediately. This allows faster turn around in the case
        where an expectation fails.

        Only exceptions that are :exc:`ElementNotFound` or any subclass thereof cause the block to
        be rerun. Drivers may specify additional exceptions which also cause reruns. This usually
        occurs when a node is manipulated which no longer exists on the page. For example, the
        Selenium driver specifies ``selenium.common.exceptions.StateElementReferenceException``.

        As long as any of these exceptions are thrown, the function is re-run, until a certain
        amount of time passes. The amount of time defaults to :data:`capybara.default_max_wait_time`
        and can be overridden through the ``wait`` argument. This time is compared with the system
        time to see how much time has passed. If the return value of ``time.time()`` is stubbed
        out, Capybara will raise :exc:`FrozenInTime`.

        Args:
            func (Callable, optional): The function to decorate.
            wait (int, optional): Number of seconds to retry this function.
            errors (Tuple[Type[Exception]], optional): Exception types that cause the function to be
                rerun. Defaults to ``driver.invalid_element_errors`` + :exc:`ElementNotFound`.

        Returns:
            Callable: The decorated function, or a decorator function.

        Raises:
            FrozenInTime: If the return value of ``time.time()`` appears stuck.
        """

        def decorator(func):
            @wraps(func)
            def outer(*args, **kwargs):
                seconds = wait if wait is not None else capybara.default_max_wait_time

                def inner():
                    return func(*args, **kwargs)

                if self.session.synchronized:
                    return inner()
                else:
                    timer = Timer(seconds)
                    self.session.synchronized = True
                    try:
                        while True:
                            try:
                                return inner()
                            except Exception as e:
                                self.session.raise_server_error()

                                if not self._should_catch_error(e, errors):
                                    raise
                                if timer.expired:
                                    raise

                                sleep(0.05)

                                if timer.stalled:
                                    raise FrozenInTime(
                                        "time appears to be frozen, Capybara does not work with "
                                        "libraries which freeze time, consider using time "
                                        "traveling instead")
                                if capybara.automatic_reload:
                                    self.reload()
                    finally:
                        self.session.synchronized = False

            return outer

        if func:
            return decorator(func)
        else:
            return decorator

This method is Capybara s primary defense against asynchronicity problems . It works by attempting to run a given decorated function until it succeeds . The exact behavior of this method depends on a number of factors . Basically there are certain exceptions which when raised from the decorated function instead of bubbling up are caught and the function is re - run .


def _should_catch_error(self, error, errors=()):
        """
        Returns whether to catch the given error.

        Args:
            error (Exception): The error to consider.
            errors (Tuple[Type[Exception], ...], optional): The exception types that should be
                caught. Defaults to :class:`ElementNotFound` plus any driver-specific invalid
                element errors.

        Returns:
            bool: Whether to catch the given error.
        """

        caught_errors = (
            errors or
            self.session.driver.invalid_element_errors + (ElementNotFound,))

        return isinstance(error, caught_errors)

def _should_catch_error ( self , error , errors = ( ) ) : caught_errors = ( errors or self . session . driver . invalid_element_errors + ( ElementNotFound , ) ) return isinstance ( error , caught_errors )

Returns whether to catch the given error .


def compare_count(self):
        """
        Returns how the result count compares to the query options.

        The return value is negative if too few results were found, zero if enough were found, and
        positive if too many were found.

        Returns:
            int: -1, 0, or 1.
        """

        if self.query.options["count"] is not None:
            count_opt = int(self.query.options["count"])
            self._cache_at_least(count_opt + 1)
            return cmp(len(self._result_cache), count_opt)

        if self.query.options["minimum"] is not None:
            min_opt = int(self.query.options["minimum"])
            if not self._cache_at_least(min_opt):
                return -1

        if self.query.options["maximum"] is not None:
            max_opt = int(self.query.options["maximum"])
            if self._cache_at_least(max_opt + 1):
                return 1

        if self.query.options["between"] is not None:
            between = self.query.options["between"]
            min_opt, max_opt = between[0], between[-1]
            if not self._cache_at_least(min_opt):
                return -1
            if self._cache_at_least(max_opt + 1):
                return 1
            return 0

        return 0

def compare_count ( self ) : if self . query . options [ "count" ] is not None : count_opt = int ( self . query . options [ "count" ] ) self . _cache_at_least ( count_opt + 1 ) return cmp ( len ( self . _result_cache ) , count_opt ) if self . query . options [ "minimum" ] is not None : min_opt = int ( self . query . options [ "minimum" ] ) if not self . _cache_at_least ( min_opt ) : return - 1 if self . query . options [ "maximum" ] is not None : max_opt = int ( self . query . options [ "maximum" ] ) if self . _cache_at_least ( max_opt + 1 ) : return 1 if self . query . options [ "between" ] is not None : between = self . query . options [ "between" ] min_opt , max_opt = between [ 0 ] , between [ - 1 ] if not self . _cache_at_least ( min_opt ) : return - 1 if self . _cache_at_least ( max_opt + 1 ) : return 1 return 0 return 0

Returns how the result count compares to the query options .


def _cache_at_least(self, size):
        """
        Attempts to fill the result cache with at least the given number of results.

        Returns:
            bool: Whether the cache contains at least the given size.
        """

        try:
            while len(self._result_cache) < size:
                self._result_cache.append(next(self._result_iter))
            return True
        except StopIteration:
            return False

def _cache_at_least ( self , size ) : try : while len ( self . _result_cache ) < size : self . _result_cache . append ( next ( self . _result_iter ) ) return True except StopIteration : return False

Attempts to fill the result cache with at least the given number of results .


def expects_none(options):
    """
    Returns whether the given query options expect a possible count of zero.

    Args:
        options (Dict[str, int | Iterable[int]]): A dictionary of query options.

    Returns:
        bool: Whether a possible count of zero is expected.
    """

    if any(options.get(key) is not None for key in ["count", "maximum", "minimum", "between"]):
        return matches_count(0, options)
    else:
        return False

def expects_none ( options ) : if any ( options . get ( key ) is not None for key in [ "count" , "maximum" , "minimum" , "between" ] ) : return matches_count ( 0 , options ) else : return False

Returns whether the given query options expect a possible count of zero .


def failure_message(description, options):
    """
    Returns a expectation failure message for the given query description.

    Args:
        description (str): A description of the failed query.
        options (Dict[str, Any]): The query options.

    Returns:
        str: A message describing the failure.
    """

    message = "expected to find {}".format(description)

    if options["count"] is not None:
        message += " {count} {times}".format(
            count=options["count"],
            times=declension("time", "times", options["count"]))
    elif options["between"] is not None:
        between = options["between"]
        if between:
            first, last = between[0], between[-1]
        else:
            first, last = None, None

        message += " between {first} and {last} times".format(
            first=first,
            last=last)
    elif options["maximum"] is not None:
        message += " at most {maximum} {times}".format(
            maximum=options["maximum"],
            times=declension("time", "times", options["maximum"]))
    elif options["minimum"] is not None:
        message += " at least {minimum} {times}".format(
            minimum=options["minimum"],
            times=declension("time", "times", options["minimum"]))

    return message

def
failure_message
(
description
,
options
)
:
message
=
"expected to find {}"
.
format
(
description
)
if
options
[
"count"
]
is
not
:
message
+=
" {count} {times}"
.
format
(
count
=
options
[
"count"
]
,
times
=
declension
(
"time"
,
"times"
,
options
[
"count"
]
)
)
elif
options
[
"between"
]
is
not
:
between
=
options
[
"between"
]
if
between
:
first
,
last
=
between
[
0
]
,
between
[
1
]
else
:
first
,
last
=
,
message
+=
" between {first} and {last} times"
.
format
(
first
=
first
,
last
=
last
)
elif
options
[
"maximum"
]
is
not
:
message
+=
" at most {maximum} {times}"
.
format
(
maximum
=
options
[
"maximum"
]
,
times
=
declension
(
"time"
,
"times"
,
options
[
"maximum"
]
)
)
elif
options
[
"minimum"
]
is
not
:
message
+=
" at least {minimum} {times}"
.
format
(
minimum
=
options
[
"minimum"
]
,
times
=
declension
(
"time"
,
"times"
,
options
[
"minimum"
]
)
)
return
message

Returns a expectation failure message for the given query description .


def matches_count(count, options):
    """
    Returns whether the given count matches the given query options.

    If no quantity options are specified, any count is considered acceptable.

    Args:
        count (int): The count to be validated.
        options (Dict[str, int | Iterable[int]]): A dictionary of query options.

    Returns:
        bool: Whether the count matches the options.
    """

    if options.get("count") is not None:
        return count == int(options["count"])
    if options.get("maximum") is not None and int(options["maximum"]) < count:
        return False
    if options.get("minimum") is not None and int(options["minimum"]) > count:
        return False
    if options.get("between") is not None and count not in options["between"]:
        return False
    return True

def matches_count ( count , options ) : if options . get ( "count" ) is not None : return count == int ( options [ "count" ] ) if options . get ( "maximum" ) is not None and int ( options [ "maximum" ] ) < count : return False if options . get ( "minimum" ) is not None and int ( options [ "minimum" ] ) > count : return False if options . get ( "between" ) is not None and count not in options [ "between" ] : return False return True

Returns whether the given count matches the given query options .


def normalize_text(value):
    """
    Normalizes the given value to a string of text with extra whitespace removed.

    Byte sequences are decoded. ``None`` is converted to an empty string. Everything else
    is simply cast to a string.

    Args:
        value (Any): The data to normalize.

    Returns:
        str: The normalized text.
    """

    if value is None:
        return ""

    text = decode_bytes(value) if isbytes(value) else str_(value)

    return normalize_whitespace(text)

def normalize_text ( value ) : if value is None : return "" text = decode_bytes ( value ) if isbytes ( value ) else str_ ( value ) return normalize_whitespace ( text )

Normalizes the given value to a string of text with extra whitespace removed .


def normalize_whitespace(text):
    """
    Returns the given text with outer whitespace removed and inner whitespace collapsed.

    Args:
        text (str): The text to normalize.

    Returns:
        str: The normalized text.
    """

    return re.sub(r"\s+", " ", text, flags=re.UNICODE).strip()

def
normalize_whitespace
(
text
)
:
return
re
.
sub
(
r"\s+"
,
" "
,
text
,
flags
=
re
.
UNICODE
)
.
strip
(
)

Returns the given text with outer whitespace removed and inner whitespace collapsed .


def toregex(text, exact=False):
    """
    Returns a compiled regular expression for the given text.

    Args:
        text (str | RegexObject): The text to match.
        exact (bool, optional): Whether the generated regular expression should match exact
            strings. Defaults to False.

    Returns:
        RegexObject: A compiled regular expression that will match the text.
    """

    if isregex(text):
        return text

    escaped = re.escape(normalize_text(text))
    if exact:
        escaped = r"\A{}\Z".format(escaped)

    return re.compile(escaped)

def toregex ( text , exact = False ) : if isregex ( text ) : return text escaped = re . escape ( normalize_text ( text ) ) if exact : escaped = r"\A{}\Z" . format ( escaped ) return re . compile ( escaped )

Returns a compiled regular expression for the given text .


def resolves_for(self, session):
        """
        Returns whether this query resolves for the given session.

        Args:
            session (Session): The session for which this query should be executed.

        Returns:
            bool: Whether this query resolves.
        """

        if self.url:
            self.actual_path = session.current_url
        else:
            result = urlparse(session.current_url)

            if self.only_path:
                self.actual_path = result.path
            else:
                request_uri = result.path
                if result.query:
                    request_uri += "?{0}".format(result.query)

                self.actual_path = request_uri

        if isregex(self.expected_path):
            return self.expected_path.search(self.actual_path)
        else:
            return normalize_url(self.actual_path) == normalize_url(self.expected_path)

def resolves_for ( self , session ) : if self . url : self . actual_path = session . current_url else : result = urlparse ( session . current_url ) if self . only_path : self . actual_path = result . path else : request_uri = result . path if result . query : request_uri += "?{0}" . format ( result . query ) self . actual_path = request_uri if isregex ( self . expected_path ) : return self . expected_path . search ( self . actual_path ) else : return normalize_url ( self . actual_path ) == normalize_url ( self . expected_path )

Returns whether this query resolves for the given session .


def resize_to(self, width, height):
        """
        Resizes the window to the given dimensions.

        If this method was called for a window that is not current, then after calling this method
        the current window should remain the same as it was before calling this method.

        Args:
            width (int): The new window width in pixels.
            height (int): The new window height in pixels.
        """

        self.driver.resize_window_to(self.handle, width, height)

def resize_to ( self , width , height ) : self . driver . resize_window_to ( self . handle , width , height )

Resizes the window to the given dimensions .


def boot(self):
        """
        Boots a server for the app, if it isn't already booted.

        Returns:
            Server: This server.
        """

        if not self.responsive:
            # Remember the port so we can reuse it if we try to serve this same app again.
            type(self)._ports[self.port_key] = self.port

            init_func = capybara.servers[capybara.server_name]
            init_args = (self.middleware, self.port, self.host)

            self.server_thread = Thread(target=init_func, args=init_args)

            # Inform Python that it shouldn't wait for this thread to terminate before
            # exiting. (It will still be appropriately terminated when the process exits.)
            self.server_thread.daemon = True

            self.server_thread.start()

            # Make sure the server actually starts and becomes responsive.
            timer = Timer(60)
            while not self.responsive:
                if timer.expired:
                    raise RuntimeError("WSGI application timed out during boot")
                self.server_thread.join(0.1)

        return self

Boots a server for the app if it isn t already booted .


def cgetter(self, fcget: typing.Optional[typing.Callable[[typing.Any], typing.Any]]) -> "AdvancedProperty":
        """Descriptor to change the class wide getter on a property.

        :param fcget: new class-wide getter.
        :type fcget: typing.Optional[typing.Callable[[typing.Any, ], typing.Any]]
        :return: AdvancedProperty
        :rtype: AdvancedProperty
        """
        self.__fcget = fcget
        return self

def cgetter ( self , fcget : typing . Optional [ typing . Callable [ [ typing . Any ] , typing . Any ] ] ) -> "AdvancedProperty" : self . __fcget = fcget return self

Descriptor to change the class wide getter on a property .


def instance_method(self, imeth: typing.Optional[typing.Callable[..., typing.Any]]) -> "SeparateClassMethod":
        """Descriptor to change instance method.

        :param imeth: New instance method.
        :type imeth: typing.Optional[typing.Callable]
        :return: SeparateClassMethod
        :rtype: SeparateClassMethod
        """
        self.__instance_method = imeth
        return self

def instance_method ( self , imeth : typing . Optional [ typing . Callable [ ... , typing . Any ] ] ) -> "SeparateClassMethod" : self . __instance_method = imeth return self


def class_method(self, cmeth: typing.Optional[typing.Callable[..., typing.Any]]) -> "SeparateClassMethod":
        """Descriptor to change class method.

        :param cmeth: New class method.
        :type cmeth: typing.Optional[typing.Callable]
        :return: SeparateClassMethod
        :rtype: SeparateClassMethod
        """
        self.__class_method = cmeth
        return self

def class_method ( self , cmeth : typing . Optional [ typing . Callable [ ... , typing . Any ] ] ) -> "SeparateClassMethod" : self . __class_method = cmeth return self


def __traceback(self) -> str:
        """Get outer traceback text for logging."""
        if not self.log_traceback:
            return ""
        exc_info = sys.exc_info()
        stack = traceback.extract_stack()
        exc_tb = traceback.extract_tb(exc_info[2])
        full_tb = stack[:1] + exc_tb  # cut decorator and build full traceback
        exc_line: typing.List[str] = traceback.format_exception_only(*exc_info[:2])
        # Make standard traceback string
        tb_text = "\nTraceback (most recent call last):\n" + "".join(traceback.format_list(full_tb)) + "".join(exc_line)
        return tb_text


def __get_obj_source(self, instance: typing.Any, owner: typing.Optional[type] = None) -> str:
        """Get object repr block."""
        if self.log_object_repr:
            return f"{instance!r}"
        return f"<{owner.__name__ if owner is not None else instance.__class__.__name__}() at 0x{id(instance):X}>"


def _get_logger_for_instance(self, instance: typing.Any) -> logging.Logger:
        """Get logger for log calls.

        :param instance: Owner class instance. Filled only if instance created, else None.
        :type instance: typing.Optional[owner]
        :return: logger instance
        :rtype: logging.Logger
        """
        if self.logger is not None:  # pylint: disable=no-else-return
            return self.logger
        elif hasattr(instance, "logger") and isinstance(instance.logger, logging.Logger):
            return instance.logger
        elif hasattr(instance, "log") and isinstance(instance.log, logging.Logger):
            return instance.log
        return _LOGGER

def _get_logger_for_instance ( self , instance : typing . Any ) -> logging . Logger : if self . logger is not None : return self . logger elif hasattr ( instance , "logger" ) and isinstance ( instance . logger , logging . Logger ) : return instance . logger elif hasattr ( instance , "log" ) and isinstance ( instance . log , logging . Logger ) : return instance . log return _LOGGER


def logger(self, logger: typing.Union[logging.Logger, str, None]) -> None:
        """Logger instance to use as override."""
        if logger is None or isinstance(logger, logging.Logger):
            self.__logger = logger
        else:
            self.__logger = logging.getLogger(logger)

def logger ( self , logger : typing . Union [ logging . Logger , str , None ] ) -> None : if logger is None or isinstance ( logger , logging . Logger ) : self . __logger = logger else : self . __logger = logging . getLogger ( logger )


def _call_api(self, method, params=None):
        """
        Low-level method to call the Slack API.

        Args:
            method: {str} method name to call
            params: {dict} GET parameters
                The token will always be added
        """
        url = self.url.format(method=method)
        if not params:
            params = {'token': self.token}
        else:
            params['token'] = self.token
        logger.debug('Send request to %s', url)
        response = requests.get(url, params=params).json()
        if self.verify:
            if not response['ok']:
                msg = 'For {url} API returned this bad response {response}'
                raise Exception(msg.format(url=url, response=response))
        return response

Low - level method to call the Slack API .


def channels(self):
        """
        List of channels of this slack team
        """
        if not self._channels:
            self._channels = self._call_api('channels.list')['channels']
        return self._channels

def channels ( self ) : if not self . _channels : self . _channels = self . _call_api ( 'channels.list' ) [ 'channels' ] return self . _channels


def users(self):
        """
        List of users of this slack team
        """
        if not self._users:
            self._users = self._call_api('users.list')['members']
        return self._users

def users ( self ) : if not self . _users : self . _users = self . _call_api ( 'users.list' ) [ 'members' ] return self . _users


def make_message(self, text, channel):
        """
        High-level function for creating messages. Return packed bytes.

        Args:
            text: {str}
            channel: {str} Either name or ID
        """
        try:
            channel_id = self.slack.channel_from_name(channel)['id']
        except ValueError:
            channel_id = channel
        return pack({
            'text': text,
            'type': 'message',
            'channel': channel_id,
            'id': self.message_id,
        })

def make_message ( self , text , channel ) : try : channel_id = self . slack . channel_from_name ( channel ) [ 'id' ] except ValueError : channel_id = channel return pack ( { 'text' : text , 'type' : 'message' , 'channel' : channel_id , 'id' : self . message_id , } )

High - level function for creating messages . Return packed bytes .


def translate(self, message):
        """
        Translate machine identifiers into human-readable
        """
        # translate user
        try:
            user_id = message.pop('user')
            user = self.slack.user_from_id(user_id)
            message[u'user'] = user['name']
        except (KeyError, IndexError, ValueError):
            pass
        # translate channel
        try:
            if type(message['channel']) == str:
                channel_id = message.pop('channel')
            else:
                channel_id = message.pop('channel')['id']
                self.slack.reload_channels()
            channel = self.slack.channel_from_id(channel_id)
            message[u'channel'] = channel['name']
        except (KeyError, IndexError, ValueError):
            pass
        return message

def translate ( self , message ) : try : user_id = message . pop ( 'user' ) user = self . slack . user_from_id ( user_id ) message [ u'user' ] = user [ 'name' ] except ( KeyError , IndexError , ValueError ) : pass try : if type ( message [ 'channel' ] ) == str : channel_id = message . pop ( 'channel' ) else : channel_id = message . pop ( 'channel' ) [ 'id' ] self . slack . reload_channels ( ) channel = self . slack . channel_from_id ( channel_id ) message [ u'channel' ] = channel [ 'name' ] except ( KeyError , IndexError , ValueError ) : pass return message

Translate machine identifiers into human - readable


def sendSlack(self, message):
        """
        Send message to Slack
        """
        channel = message.get('channel', 'general')
        self.sendMessage(self.make_message(message['text'], channel))

def sendSlack ( self , message ) : channel = message . get ( 'channel' , 'general' ) self . sendMessage ( self . make_message ( message [ 'text' ] , channel ) )


def read_channel(self):
        """
        Get available messages and send through to the protocol
        """
        channel, message = self.protocol.channel_layer.receive_many([u'slack.send'], block=False)
        delay = 0.1
        if channel:
            self.protocols[0].sendSlack(message)
        reactor.callLater(delay, self.read_channel)

def read_channel ( self ) : channel , message = self . protocol . channel_layer . receive_many ( [ u'slack.send' ] , block = False ) delay = 0.1 if channel : self . protocols [ 0 ] . sendSlack ( message ) reactor . callLater ( delay , self . read_channel )


def run(self):
        """
        Main interface. Instantiate the SlackAPI, connect to RTM
        and start the client.
        """
        slack = SlackAPI(token=self.token)
        rtm = slack.rtm_start()

        factory = SlackClientFactory(rtm['url'])
        # Attach attributes
        factory.protocol = SlackClientProtocol
        factory.protocol.slack = slack
        factory.protocol.channel_layer = self.channel_layer
        factory.channel_name = self.channel_name

        # Here we go
        factory.run()

def run ( self ) : slack = SlackAPI ( token = self . token ) rtm = slack . rtm_start ( ) factory = SlackClientFactory ( rtm [ 'url' ] ) factory . protocol = SlackClientProtocol factory . protocol . slack = slack factory . protocol . channel_layer = self . channel_layer factory . channel_name = self . channel_name factory . run ( )

Main interface . Instantiate the SlackAPI connect to RTM and start the client .


def run(self, args):
        """
        Pass in raw arguments, instantiate Slack API and begin client.
        """
        args = self.parser.parse_args(args)
        if not args.token:
            raise ValueError('Supply the slack token through --token or setting DJANGOBOT_TOKEN')

        # Import the channel layer
        sys.path.insert(0, ".")
        module_path, object_path = args.channel_layer.split(':', 1)
        channel_layer = importlib.import_module(module_path)
        for part in object_path.split('.'):
            channel_layer = getattr(channel_layer, part)

        # Boot up the client
        Client(
            channel_layer=channel_layer,
            token=args.token,
        ).run()

Pass in raw arguments instantiate Slack API and begin client .


def dict_diff(prv, nxt):
    """Return a dict of keys that differ with another config object."""
    keys = set(prv.keys() + nxt.keys())
    result = {}
    for k in keys:
        if prv.get(k) != nxt.get(k):
            result[k] = (prv.get(k), nxt.get(k))
    return result

def dict_diff ( prv , nxt ) : keys = set ( prv . keys ( ) + nxt . keys ( ) ) result = { } for k in keys : if prv . get ( k ) != nxt . get ( k ) : result [ k ] = ( prv . get ( k ) , nxt . get ( k ) ) return result

Return a dict of keys that differ with another config object .


def colorize(msg, color):
    """Given a string add necessary codes to format the string."""
    if DONT_COLORIZE:
        return msg
    else:
        return "{}{}{}".format(COLORS[color], msg, COLORS["endc"])

def colorize ( msg , color ) : if DONT_COLORIZE : return msg else : return "{}{}{}" . format ( COLORS [ color ] , msg , COLORS [ "endc" ] )

Given a string add necessary codes to format the string .


def v2_playbook_on_task_start(self, task, **kwargs):
        """Run when a task starts."""
        self.last_task_name = task.get_name()
        self.printed_last_task = False

def v2_playbook_on_task_start ( self , task , ** kwargs ) : self . last_task_name = task . get_name ( ) self . printed_last_task = False


def v2_runner_on_ok(self, result, **kwargs):
        """Run when a task finishes correctly."""
        failed = "failed" in result._result
        unreachable = "unreachable" in result._result

        if (
            "print_action" in result._task.tags
            or failed
            or unreachable
            or self._display.verbosity > 1
        ):
            self._print_task()
            self.last_skipped = False
            msg = unicode(result._result.get("msg", "")) or unicode(
                result._result.get("reason", "")
            ) or unicode(
                result._result.get("message", "")
            )

            stderr = [
                result._result.get("exception", None),
                result._result.get("module_stderr", None),
            ]
            stderr = "\n".join([e for e in stderr if e]).strip()

            self._print_host_or_item(
                result._host,
                result._result.get("changed", False),
                msg,
                result._result.get("diff", None),
                is_host=True,
                error=failed or unreachable,
                stdout=result._result.get("module_stdout", None),
                stderr=stderr.strip(),
            )

            if "results" in result._result:
                for r in result._result["results"]:
                    failed = "failed" in r

                    stderr = [r.get("exception", None), r.get("module_stderr", None)]
                    stderr = "\n".join([e for e in stderr if e]).strip()

                    self._print_host_or_item(
                        r["item"],
                        r.get("changed", False),
                        unicode(r.get("msg", "")),
                        r.get("diff", None),
                        is_host=False,
                        error=failed,
                        stdout=r.get("module_stdout", None),
                        stderr=stderr.strip(),
                    )
        else:
            self.last_skipped = True
            print(".", end="")

def v2_runner_on_ok ( self , result , ** kwargs ) : failed = "failed" in result . _result unreachable = "unreachable" in result . _result if ( "print_action" in result . _task . tags or failed or unreachable or self . _display . verbosity > 1 ) : self . _print_task ( ) self . last_skipped = False msg = unicode ( result . _result . get ( "msg" , "" ) ) or unicode ( result . _result . get ( "reason" , "" ) ) or unicode ( result . _result . get ( "message" , "" ) ) stderr = [ result . _result . get ( "exception" , None ) , result . _result . get ( "module_stderr" , None ) , ] stderr = "\n" . join ( [ e for e in stderr if e ] ) . strip ( ) self . _print_host_or_item ( result . _host , result . _result . get ( "changed" , False ) , msg , result . _result . get ( "diff" , None ) , is_host = True , error = failed or unreachable , stdout = result . _result . get ( "module_stdout" , None ) , stderr = stderr . strip ( ) , ) if "results" in result . _result : for r in result . _result [ "results" ] : failed = "failed" in r stderr = [ r . get ( "exception" , None ) , r . get ( "module_stderr" , None ) ] stderr = "\n" . join ( [ e for e in stderr if e ] ) . strip ( ) self . _print_host_or_item ( r [ "item" ] , r . get ( "changed" , False ) , unicode ( r . get ( "msg" , "" ) ) , r . get ( "diff" , None ) , is_host = False , error = failed , stdout = r . get ( "module_stdout" , None ) , stderr = stderr . strip ( ) , ) else : self . last_skipped = True print ( "." , end = "" )


def v2_playbook_on_stats(self, stats):
        """Display info about playbook statistics."""
        print()
        self.printed_last_task = False
        self._print_task("STATS")

        hosts = sorted(stats.processed.keys())
        for host in hosts:
            s = stats.summarize(host)

            if s["failures"] or s["unreachable"]:
                color = "failed"
            elif s["changed"]:
                color = "changed"
            else:
                color = "ok"

            msg = "{}    : ok={}\tchanged={}\tfailed={}\tunreachable={}".format(
                host, s["ok"], s["changed"], s["failures"], s["unreachable"]
            )
            print(colorize(msg, color))

Display info about playbook statistics .


def v2_runner_on_skipped(self, result, **kwargs):
        """Run when a task is skipped."""
        if self._display.verbosity > 1:
            self._print_task()
            self.last_skipped = False

            line_length = 120
            spaces = " " * (31 - len(result._host.name) - 4)

            line = "  * {}{}- {}".format(
                colorize(result._host.name, "not_so_bold"),
                spaces,
                colorize("skipped", "skipped"),
            )

            reason = result._result.get("skipped_reason", "") or result._result.get(
                "skip_reason", ""
            )
            if len(reason) < 50:
                line += " -- {}".format(reason)
                print("{} {}---------".format(line, "-" * (line_length - len(line))))
            else:
                print("{} {}".format(line, "-" * (line_length - len(line))))
                print(self._indent_text(reason, 8))
                print(reason)

def
v2_runner_on_skipped
(
self
,
result
,
**
kwargs
)
:
if
self
.
_display
.
verbosity
>
1
:
self
.
_print_task
(
)
self
.
last_skipped
=
False
line_length
=
120
spaces
=
" "
*
(
31
len
(
result
.
_host
.
name
)
4
)
line
=
"  * {}{}- {}"
.
format
(
colorize
(
result
.
_host
.
name
,
"not_so_bold"
)
,
spaces
,
colorize
(
"skipped"
,
"skipped"
)
,
)
reason
=
result
.
_result
.
get
(
"skipped_reason"
,
""
)
or
result
.
_result
.
get
(
"skip_reason"
,
""
)
if
len
(
reason
)
<
50
:
line
+=
" -- {}"
.
format
(
reason
)
print
(
"{} {}---------"
.
format
(
line
,
"-"
*
(
line_length
len
(
line
)
)
)
)
else
:
print
(
"{} {}"
.
format
(
line
,
"-"
*
(
line_length
len
(
line
)
)
)
)
print
(
self
.
_indent_text
(
reason
,
8
)
)
print
(
reason
)


def prefix_to_addrmask(value, sep=" "):
    """
    Converts a CIDR formatted prefix into an address netmask representation.
    Argument sep specifies the separator between the address and netmask parts.
    By default it's a single space.

    Examples:
        >>> "{{ '192.168.0.1/24|prefix_to_addrmask }}" -> "192.168.0.1 255.255.255.0"
        >>> "{{ '192.168.0.1/24|prefix_to_addrmask('/') }}" -> "192.168.0.1/255.255.255.0"
    """
    prefix = netaddr.IPNetwork(value)
    return "{}{}{}".format(prefix.ip, sep, prefix.netmask)

def
prefix_to_addrmask
(
value
,
sep
=
" "
)
:
prefix
=
netaddr
.
IPNetwork
(
value
)
return
"{}{}{}"
.
format
(
prefix
.
ip
,
sep
,
prefix
.
netmask
)

Converts a CIDR formatted prefix into an address netmask representation . Argument sep specifies the separator between the address and netmask parts . By default it s a single space .


def check_empty(default=""):
    """
    Decorator that checks if a value passed to a Jinja filter evaluates to false
    and returns an empty string. Otherwise calls the original Jinja filter.

    Example usage:
    @check_empty
    def my_jinja_filter(value, arg1):
    """

    def real_decorator(func):

        @wraps(func)
        def wrapper(value, *args, **kwargs):
            if not value:
                return default
            else:
                return func(value, *args, **kwargs)

        return wrapper

    return real_decorator

def check_empty ( default = "" ) : def real_decorator ( func ) : @ wraps ( func ) def wrapper ( value , * args , ** kwargs ) : if not value : return default else : return func ( value , * args , ** kwargs ) return wrapper return real_decorator

Decorator that checks if a value passed to a Jinja filter evaluates to false and returns an empty string . Otherwise calls the original Jinja filter .


def add_model(self, model, force=False):
        """
        Add a model.

        The model will be asssigned to a class attribute with the YANG name of the model.

        Args:
            model (PybindBase): Model to add.
            force (bool): If not set, verify the model is in SUPPORTED_MODELS

        Examples:

            >>> import napalm_yang
            >>> config = napalm_yang.base.Root()
            >>> config.add_model(napalm_yang.models.openconfig_interfaces)
            >>> config.interfaces
            <pyangbind.lib.yangtypes.YANGBaseClass object at 0x10bef6680>
        """
        if isinstance(model, str):
            self._load_model(model)
            return

        try:
            model = model()
        except Exception:
            pass

        if model._yang_name not in [a[0] for a in SUPPORTED_MODELS] and not force:
            raise ValueError(
                "Only models in SUPPORTED_MODELS can be added without `force=True`"
            )

        for k, v in model:
            self._elements[k] = v
            setattr(self, k, v)


def get(self, filter=False):
        """
        Returns a dictionary with the values of the model. Note that the values
        of the leafs are YANG classes.

        Args:
            filter (bool): If set to ``True``, show only values that have been set.

        Returns:
            dict: A dictionary with the values of the model.

        Example:

            >>> pretty_print(config.get(filter=True))
            >>> {
            >>>     "interfaces": {
            >>>         "interface": {
            >>>             "et1": {
            >>>                 "config": {
            >>>                     "description": "My description",
            >>>                     "mtu": 1500
            >>>                 },
            >>>                 "name": "et1"
            >>>             },
            >>>             "et2": {
            >>>                 "config": {
            >>>                     "description": "Another description",
            >>>                     "mtu": 9000
            >>>                 },
            >>>                 "name": "et2"
            >>>             }
            >>>         }
            >>>     }
            >>> }

        """
        result = {}

        for k, v in self.elements().items():
            intermediate = v.get(filter=filter)
            if intermediate:
                result[k] = intermediate

        return result

def get ( self , filter = False ) : result = { } for k , v in self . elements ( ) . items ( ) : intermediate = v . get ( filter = filter ) if intermediate : result [ k ] = intermediate return result

Returns a dictionary with the values of the model . Note that the values of the leafs are YANG classes .


def load_dict(self, data, overwrite=False, auto_load_model=True):
        """
        Load a dictionary into the model.

        Args:
            data(dict): Dictionary to load
            overwrite(bool): Whether the data present in the model should be overwritten by the
                data in the dict or not.
            auto_load_model(bool): If set to true models will be loaded as they are needed

        Examples:

            >>> vlans_dict = {
            >>>     "vlans": { "vlan": { 100: {
            >>>                             "config": {
            >>>                                 "vlan_id": 100, "name": "production"}},
            >>>                          200: {
            >>>                             "config": {
            >>>                                 "vlan_id": 200, "name": "dev"}}}}}
            >>> config.load_dict(vlans_dict)
            >>> print(config.vlans.vlan.keys())
            ... [200, 100]
            >>> print(100, config.vlans.vlan[100].config.name)
            ... (100, u'production')
            >>> print(200, config.vlans.vlan[200].config.name)
            ... (200, u'dev')
        """
        for k, v in data.items():
            if k not in self._elements.keys() and not auto_load_model:
                raise AttributeError("Model {} is not loaded".format(k))

            elif k not in self._elements.keys() and auto_load_model:
                self._load_model(k)

            attr = getattr(self, k)
            _load_dict(attr, v)

def
load_dict
(
self
,
data
,
overwrite
=
False
,
auto_load_model
=
True
)
:
for
k
,
v
in
data
.
items
(
)
:
if
k
not
in
self
.
_elements
.
keys
(
)
and
not
auto_load_model
:
raise
AttributeError
(
"Model {} is not loaded"
.
format
(
k
)
)
elif
k
not
in
self
.
_elements
.
keys
(
)
and
auto_load_model
:
self
.
_load_model
(
k
)
attr
=
getattr
(
self
,
k
)
_load_dict
(
attr
,
v
)


def to_dict(self, filter=True):
        """
        Returns a dictionary with the values of the model. Note that the values
        of the leafs are evaluated to python types.

        Args:
            filter (bool): If set to ``True``, show only values that have been set.

        Returns:
            dict: A dictionary with the values of the model.

        Example:

            >>> pretty_print(config.to_dict(filter=True))
            >>> {
            >>>     "interfaces": {
            >>>         "interface": {
            >>>             "et1": {
            >>>                 "config": {
            >>>                     "description": "My description",
            >>>                     "mtu": 1500
            >>>                 },
            >>>                 "name": "et1"
            >>>             },
            >>>             "et2": {
            >>>                 "config": {
            >>>                     "description": "Another description",
            >>>                     "mtu": 9000
            >>>                 },
            >>>                 "name": "et2"
            >>>             }
            >>>         }
            >>>     }
            >>> }

        """
        result = {}
        for k, v in self:
            r = _to_dict(v, filter)
            if r:
                result[k] = r
        return result

def to_dict ( self , filter = True ) : result = { } for k , v in self : r = _to_dict ( v , filter ) if r : result [ k ] = r return result

Returns a dictionary with the values of the model . Note that the values of the leafs are evaluated to python types .


def parse_config(self, device=None, profile=None, native=None, attrs=None):
        """
        Parse native configuration and load it into the corresponding models. Only models
        that have been added to the root object will be parsed.

        If ``native`` is passed to the method that's what we will parse, otherwise, we will use the
        ``device`` to retrieve it.

        Args:
            device (NetworkDriver): Device to load the configuration from.
            profile (list): Profiles that the device supports. If no ``profile`` is passed it will
              be read from ``device``.
            native (list of strings): Native configuration to parse.

        Examples:

            >>> # Load from device
            >>> running_config = napalm_yang.base.Root()
            >>> running_config.add_model(napalm_yang.models.openconfig_interfaces)
            >>> running_config.parse_config(device=d)

            >>> # Load from file
            >>> with open("junos.config", "r") as f:
            >>>     config = f.read()
            >>>
            >>> running_config = napalm_yang.base.Root()
            >>> running_config.add_model(napalm_yang.models.openconfig_interfaces)
            >>> running_config.parse_config(native=[config], profile="junos")
        """
        if attrs is None:
            attrs = self.elements().values()

        for v in attrs:
            parser = Parser(
                v, device=device, profile=profile, native=native, is_config=True
            )
            parser.parse()

def parse_config ( self , device = None , profile = None , native = None , attrs = None ) : if attrs is None : attrs = self . elements ( ) . values ( ) for v in attrs : parser = Parser ( v , device = device , profile = profile , native = native , is_config = True ) parser . parse ( )

Parse native configuration and load it into the corresponding models . Only models that have been added to the root object will be parsed .


def parse_state(self, device=None, profile=None, native=None, attrs=None):
        """
        Parse native state and load it into the corresponding models. Only models
        that have been added to the root object will be parsed.

        If ``native`` is passed to the method that's what we will parse, otherwise, we will use the
        ``device`` to retrieve it.

        Args:
            device (NetworkDriver): Device to load the configuration from.
            profile (list): Profiles that the device supports. If no ``profile`` is passed it will
              be read from ``device``.
            native (list string): Native output to parse.

        Examples:

            >>> # Load from device
            >>> state = napalm_yang.base.Root()
            >>> state.add_model(napalm_yang.models.openconfig_interfaces)
            >>> state.parse_config(device=d)

            >>> # Load from file
            >>> with open("junos.state", "r") as f:
            >>>     state_data = f.read()
            >>>
            >>> state = napalm_yang.base.Root()
            >>> state.add_model(napalm_yang.models.openconfig_interfaces)
            >>> state.parse_config(native=[state_data], profile="junos")
        """
        if attrs is None:
            attrs = self.elements().values()

        for v in attrs:
            parser = Parser(
                v, device=device, profile=profile, native=native, is_config=False
            )
            parser.parse()

def parse_state ( self , device = None , profile = None , native = None , attrs = None ) : if attrs is None : attrs = self . elements ( ) . values ( ) for v in attrs : parser = Parser ( v , device = device , profile = profile , native = native , is_config = False ) parser . parse ( )

Parse native state and load it into the corresponding models . Only models that have been added to the root object will be parsed .


def translate_config(self, profile, merge=None, replace=None):
        """
        Translate the object to native configuration.

        In this context, merge and replace means the following:

        * **Merge** - Elements that exist in both ``self`` and ``merge`` will use by default the
          values in ``merge`` unless ``self`` specifies a new one. Elements that exist only
          in ``self`` will be translated as they are and elements present only in ``merge``
          will be removed.
        * **Replace** - All the elements in ``replace`` will either be removed or replaced by
          elements in ``self``.

        You can specify one of ``merge``, ``replace`` or none of them. If none of them are set we
        will just translate configuration.

        Args:
            profile (list): Which profiles to use.
            merge (Root): Object we want to merge with.
            replace (Root): Object we want to replace.
        """
        result = []
        for k, v in self:
            other_merge = getattr(merge, k) if merge else None
            other_replace = getattr(replace, k) if replace else None
            translator = Translator(
                v, profile, merge=other_merge, replace=other_replace
            )
            result.append(translator.translate())

        return "\n".join(result)

def translate_config ( self , profile , merge = None , replace = None ) : result = [ ] for k , v in self : other_merge = getattr ( merge , k ) if merge else None other_replace = getattr ( replace , k ) if replace else None translator = Translator ( v , profile , merge = other_merge , replace = other_replace ) result . append ( translator . translate ( ) ) return "\n" . join ( result )

Translate the object to native configuration .


def load_filters():
    """
    Loads and returns all filters.
    """
    all_filters = {}
    for m in JINJA_FILTERS:
        if hasattr(m, "filters"):
            all_filters.update(m.filters())
    return all_filters

def load_filters ( ) : all_filters = { } for m in JINJA_FILTERS : if hasattr ( m , "filters" ) : all_filters . update ( m . filters ( ) ) return all_filters


def find_yang_file(profile, filename, path):
    """
    Find the necessary file for the given test case.

    Args:
        device(napalm device connection): for which device
        filename(str): file to find
        path(str): where to find it relative to where the module is installed
    """
    # Find base_dir of submodule
    module_dir = os.path.dirname(__file__)
    full_path = os.path.join(module_dir, "mappings", profile, path, filename)

    if os.path.exists(full_path):
        return full_path
    else:
        msg = "Couldn't find parsing file: {}".format(full_path)
        logger.error(msg)
        raise IOError(msg)

def
find_yang_file
(
profile
,
filename
,
path
)
:
module_dir
=
os
.
path
.
dirname
(
__file__
)
full_path
=
os
.
path
.
join
(
module_dir
,
"mappings"
,
profile
,
path
,
filename
)
if
os
.
path
.
exists
(
full_path
)
:
return
full_path
else
:
msg
=
"Couldn't find parsing file: {}"
.
format
(
full_path
)
logger
.
error
(
msg
)
raise
IOError
(
msg
)

Find the necessary file for the given test case .


def model_to_dict(model, mode="", show_defaults=False):
    """
    Given a model, return a representation of the model in a dict.

    This is mostly useful to have a quick visual represenation of the model.

    Args:

        model (PybindBase): Model to transform.
        mode (string): Whether to print config, state or all elements ("" for all)

    Returns:

        dict: A dictionary representing the model.

    Examples:

        >>> config = napalm_yang.base.Root()
        >>>
        >>> # Adding models to the object
        >>> config.add_model(napalm_yang.models.openconfig_interfaces())
        >>> config.add_model(napalm_yang.models.openconfig_vlan())
        >>> # Printing the model in a human readable format
        >>> pretty_print(napalm_yang.utils.model_to_dict(config))
        >>> {
        >>>     "openconfig-interfaces:interfaces [rw]": {
        >>>         "interface [rw]": {
        >>>             "config [rw]": {
        >>>                 "description [rw]": "string",
        >>>                 "enabled [rw]": "boolean",
        >>>                 "mtu [rw]": "uint16",
        >>>                 "name [rw]": "string",
        >>>                 "type [rw]": "identityref"
        >>>             },
        >>>             "hold_time [rw]": {
        >>>                 "config [rw]": {
        >>>                     "down [rw]": "uint32",
        >>>                     "up [rw]": "uint32"
            (trimmed for clarity)
    """

    def is_mode(obj, mode):
        if mode == "":
            return True
        elif mode == "config":
            return obj._yang_name == "config" or obj._is_config
        elif mode == "state":
            return obj._yang_name == "state" or not obj._is_config
        else:
            raise ValueError(
                "mode can only be config, state or ''. Passed: {}".format(mode)
            )

    def get_key(key, model, parent_defining_module, show_defaults):
        if not show_defaults:
            # No need to display rw/ro when showing the defaults.
            key = "{} {}".format(key, "[rw]" if model._is_config else "[ro]")
        if parent_defining_module != model._defining_module:
            key = "{}:{}".format(model._defining_module, key)
        return key

    if model._yang_type in ("container", "list"):
        cls = model if model._yang_type in ("container",) else model._contained_class()
        result = {}
        for k, v in cls:
            r = model_to_dict(v, mode=mode, show_defaults=show_defaults)
            if r:
                result[get_key(k, v, model._defining_module, show_defaults)] = r
        return result
    else:
        if show_defaults:
            if model._default is False:
                if model._yang_type != "boolean":
                    # Unless the datatype is bool, when the _default attribute
                    # is False, it means there is not default value defined in
                    # the YANG model.
                    return None
            return model._default
        return model._yang_type if is_mode(model, mode) else None

Given a model return a representation of the model in a dict .


def diff(f, s):
    """
    Given two models, return the difference between them.

    Args:

        f (Pybindbase): First element.
        s (Pybindbase): Second element.

    Returns:

        dict: A dictionary highlighting the differences.

    Examples:

        >>> diff = napalm_yang.utils.diff(candidate, running)
        >>> pretty_print(diff)
        >>> {
        >>>     "interfaces": {
        >>>         "interface": {
        >>>             "both": {
        >>>                 "Port-Channel1": {
        >>>                     "config": {
        >>>                         "mtu": {
        >>>                             "first": "0",
        >>>                             "second": "9000"
        >>>                         }
        >>>                     }
        >>>                 }
        >>>             },
        >>>             "first_only": [
        >>>                 "Loopback0"
        >>>             ],
        >>>             "second_only": [
        >>>                 "Loopback1"
        >>>             ]
        >>>         }
        >>>     }
        >>> }
    """
    if isinstance(f, base.Root) or f._yang_type in ("container", None):
        result = _diff_root(f, s)
    elif f._yang_type in ("list",):
        result = _diff_list(f, s)
    else:
        result = {}
        first = "{}".format(f)
        second = "{}".format(s)
        if first != second:
            result = {"first": first, "second": second}

    return result

def diff ( f , s ) : if isinstance ( f , base . Root ) or f . _yang_type in ( "container" , None ) : result = _diff_root ( f , s ) elif f . _yang_type in ( "list" , ) : result = _diff_list ( f , s ) else : result = { } first = "{}" . format ( f ) second = "{}" . format ( s ) if first != second : result = { "first" : first , "second" : second } return result

Given two models return the difference between them .


def http_post(self, url, data=None):
        """POST to URL and get result as a response object.

        :param url: URL to POST.
        :type url: str
        :param data: Data to send in the form body.
        :type data: str
        :rtype: requests.Response
        """
        if not url.startswith('https://'):
            raise ValueError('Protocol must be HTTPS, invalid URL: %s' % url)
        return requests.post(url, data, verify=True)

POST to URL and get result as a response object .


def get_authorization_code_uri(self, **params):
        """Construct a full URL that can be used to obtain an authorization
        code from the provider authorization_uri. Use this URI in a client
        frame to cause the provider to generate an authorization code.

        :rtype: str
        """
        if 'response_type' not in params:
            params['response_type'] = self.default_response_type
        params.update({'client_id': self.client_id,
                       'redirect_uri': self.redirect_uri})
        return utils.build_url(self.authorization_uri, params)

def get_authorization_code_uri ( self , ** params ) : if 'response_type' not in params : params [ 'response_type' ] = self . default_response_type params . update ( { 'client_id' : self . client_id , 'redirect_uri' : self . redirect_uri } ) return utils . build_url ( self . authorization_uri , params )

Construct a full URL that can be used to obtain an authorization code from the provider authorization_uri . Use this URI in a client frame to cause the provider to generate an authorization code .


def get_token(self, code, **params):
        """Get an access token from the provider token URI.

        :param code: Authorization code.
        :type code: str
        :return: Dict containing access token, refresh token, etc.
        :rtype: dict
        """
        params['code'] = code
        if 'grant_type' not in params:
            params['grant_type'] = self.default_grant_type
        params.update({'client_id': self.client_id,
                       'client_secret': self.client_secret,
                       'redirect_uri': self.redirect_uri})
        response = self.http_post(self.token_uri, params)
        try:
            return response.json()
        except TypeError:
            return response.json

def get_token ( self , code , ** params ) : params [ 'code' ] = code if 'grant_type' not in params : params [ 'grant_type' ] = self . default_grant_type params . update ( { 'client_id' : self . client_id , 'client_secret' : self . client_secret , 'redirect_uri' : self . redirect_uri } ) response = self . http_post ( self . token_uri , params ) try : return response . json ( ) except TypeError : return response . json

Get an access token from the provider token URI .


def url_query_params(url):
    """Return query parameters as a dict from the specified URL.

    :param url: URL.
    :type url: str
    :rtype: dict
    """
    return dict(urlparse.parse_qsl(urlparse.urlparse(url).query, True))

def url_query_params ( url ) : return dict ( urlparse . parse_qsl ( urlparse . urlparse ( url ) . query , True ) )

Return query parameters as a dict from the specified URL .


def url_dequery(url):
    """Return a URL with the query component removed.

    :param url: URL to dequery.
    :type url: str
    :rtype: str
    """
    url = urlparse.urlparse(url)
    return urlparse.urlunparse((url.scheme,
                                url.netloc,
                                url.path,
                                url.params,
                                '',
                                url.fragment))

def url_dequery ( url ) : url = urlparse . urlparse ( url ) return urlparse . urlunparse ( ( url . scheme , url . netloc , url . path , url . params , '' , url . fragment ) )

Return a URL with the query component removed .


def build_url(base, additional_params=None):
    """Construct a URL based off of base containing all parameters in
    the query portion of base plus any additional parameters.

    :param base: Base URL
    :type base: str
    ::param additional_params: Additional query parameters to include.
    :type additional_params: dict
    :rtype: str
    """
    url = urlparse.urlparse(base)
    query_params = {}
    query_params.update(urlparse.parse_qsl(url.query, True))
    if additional_params is not None:
        query_params.update(additional_params)
        for k, v in additional_params.iteritems():
            if v is None:
                query_params.pop(k)

    return urlparse.urlunparse((url.scheme,
                                url.netloc,
                                url.path,
                                url.params,
                                urllib.urlencode(query_params),
                                url.fragment))

def build_url ( base , additional_params = None ) : url = urlparse . urlparse ( base ) query_params = { } query_params . update ( urlparse . parse_qsl ( url . query , True ) ) if additional_params is not None : query_params . update ( additional_params ) for k , v in additional_params . iteritems ( ) : if v is None : query_params . pop ( k ) return urlparse . urlunparse ( ( url . scheme , url . netloc , url . path , url . params , urllib . urlencode ( query_params ) , url . fragment ) )

Construct a URL based off of base containing all parameters in the query portion of base plus any additional parameters .


def _handle_exception(self, exc):
        """Handle an internal exception that was caught and suppressed.

        :param exc: Exception to process.
        :type exc: Exception
        """
        logger = logging.getLogger(__name__)
        logger.exception(exc)

def _handle_exception ( self , exc ) : logger = logging . getLogger ( __name__ ) logger . exception ( exc )

Handle an internal exception that was caught and suppressed .


def _make_response(self, body='', headers=None, status_code=200):
        """Return a response object from the given parameters.

        :param body: Buffer/string containing the response body.
        :type body: str
        :param headers: Dict of headers to include in the requests.
        :type headers: dict
        :param status_code: HTTP status code.
        :type status_code: int
        :rtype: requests.Response
        """
        res = Response()
        res.status_code = status_code
        if headers is not None:
            res.headers.update(headers)
        res.raw = StringIO(body)
        return res

def _make_response ( self , body = '' , headers = None , status_code = 200 ) : res = Response ( ) res . status_code = status_code if headers is not None : res . headers . update ( headers ) res . raw = StringIO ( body ) return res

Return a response object from the given parameters .


def _make_redirect_error_response(self, redirect_uri, err):
        """Return a HTTP 302 redirect response object containing the error.

        :param redirect_uri: Client redirect URI.
        :type redirect_uri: str
        :param err: OAuth error message.
        :type err: str
        :rtype: requests.Response
        """
        params = {
            'error': err,
            'response_type': None,
            'client_id': None,
            'redirect_uri': None
        }
        redirect = utils.build_url(redirect_uri, params)
        return self._make_response(headers={'Location': redirect},
                                   status_code=302)

def _make_redirect_error_response ( self , redirect_uri , err ) : params = { 'error' : err , 'response_type' : None , 'client_id' : None , 'redirect_uri' : None } redirect = utils . build_url ( redirect_uri , params ) return self . _make_response ( headers = { 'Location' : redirect } , status_code = 302 )

Return a HTTP 302 redirect response object containing the error .


def _make_json_response(self, data, headers=None, status_code=200):
        """Return a response object from the given JSON data.

        :param data: Data to JSON-encode.
        :type data: mixed
        :param headers: Dict of headers to include in the requests.
        :type headers: dict
        :param status_code: HTTP status code.
        :type status_code: int
        :rtype: requests.Response
        """
        response_headers = {}
        if headers is not None:
            response_headers.update(headers)
        response_headers['Content-Type'] = 'application/json;charset=UTF-8'
        response_headers['Cache-Control'] = 'no-store'
        response_headers['Pragma'] = 'no-cache'
        return self._make_response(json.dumps(data),
                                   response_headers,
                                   status_code)

def _make_json_response ( self , data , headers = None , status_code = 200 ) : response_headers = { } if headers is not None : response_headers . update ( headers ) response_headers [ 'Content-Type' ] = 'application/json;charset=UTF-8' response_headers [ 'Cache-Control' ] = 'no-store' response_headers [ 'Pragma' ] = 'no-cache' return self . _make_response ( json . dumps ( data ) , response_headers , status_code )

Return a response object from the given JSON data .


def get_authorization_code(self,
                               response_type,
                               client_id,
                               redirect_uri,
                               **params):
        """Generate authorization code HTTP response.

        :param response_type: Desired response type. Must be exactly "code".
        :type response_type: str
        :param client_id: Client ID.
        :type client_id: str
        :param redirect_uri: Client redirect URI.
        :type redirect_uri: str
        :rtype: requests.Response
        """

        # Ensure proper response_type
        if response_type != 'code':
            err = 'unsupported_response_type'
            return self._make_redirect_error_response(redirect_uri, err)

        # Check redirect URI
        is_valid_redirect_uri = self.validate_redirect_uri(client_id,
                                                           redirect_uri)
        if not is_valid_redirect_uri:
            return self._invalid_redirect_uri_response()

        # Check conditions
        is_valid_client_id = self.validate_client_id(client_id)
        is_valid_access = self.validate_access()
        scope = params.get('scope', '')
        is_valid_scope = self.validate_scope(client_id, scope)

        # Return proper error responses on invalid conditions
        if not is_valid_client_id:
            err = 'unauthorized_client'
            return self._make_redirect_error_response(redirect_uri, err)

        if not is_valid_access:
            err = 'access_denied'
            return self._make_redirect_error_response(redirect_uri, err)

        if not is_valid_scope:
            err = 'invalid_scope'
            return self._make_redirect_error_response(redirect_uri, err)

        # Generate authorization code
        code = self.generate_authorization_code()

        # Save information to be used to validate later requests
        self.persist_authorization_code(client_id=client_id,
                                        code=code,
                                        scope=scope)

        # Return redirection response
        params.update({
            'code': code,
            'response_type': None,
            'client_id': None,
            'redirect_uri': None
        })
        redirect = utils.build_url(redirect_uri, params)
        return self._make_response(headers={'Location': redirect},
                                   status_code=302)

def get_authorization_code ( self , response_type , client_id , redirect_uri , ** params ) : if response_type != 'code' : err = 'unsupported_response_type' return self . _make_redirect_error_response ( redirect_uri , err ) is_valid_redirect_uri = self . validate_redirect_uri ( client_id , redirect_uri ) if not is_valid_redirect_uri : return self . _invalid_redirect_uri_response ( ) is_valid_client_id = self . validate_client_id ( client_id ) is_valid_access = self . validate_access ( ) scope = params . get ( 'scope' , '' ) is_valid_scope = self . validate_scope ( client_id , scope ) if not is_valid_client_id : err = 'unauthorized_client' return self . _make_redirect_error_response ( redirect_uri , err ) if not is_valid_access : err = 'access_denied' return self . _make_redirect_error_response ( redirect_uri , err ) if not is_valid_scope : err = 'invalid_scope' return self . _make_redirect_error_response ( redirect_uri , err ) code = self . generate_authorization_code ( ) self . persist_authorization_code ( client_id = client_id , code = code , scope = scope ) params . update ( { 'code' : code , 'response_type' : None , 'client_id' : None , 'redirect_uri' : None } ) redirect = utils . build_url ( redirect_uri , params ) return self . _make_response ( headers = { 'Location' : redirect } , status_code = 302 )

Generate authorization code HTTP response .


def refresh_token(self,
                      grant_type,
                      client_id,
                      client_secret,
                      refresh_token,
                      **params):
        """Generate access token HTTP response from a refresh token.

        :param grant_type: Desired grant type. Must be "refresh_token".
        :type grant_type: str
        :param client_id: Client ID.
        :type client_id: str
        :param client_secret: Client secret.
        :type client_secret: str
        :param refresh_token: Refresh token.
        :type refresh_token: str
        :rtype: requests.Response
        """

        # Ensure proper grant_type
        if grant_type != 'refresh_token':
            return self._make_json_error_response('unsupported_grant_type')

        # Check conditions
        is_valid_client_id = self.validate_client_id(client_id)
        is_valid_client_secret = self.validate_client_secret(client_id,
                                                             client_secret)
        scope = params.get('scope', '')
        is_valid_scope = self.validate_scope(client_id, scope)
        data = self.from_refresh_token(client_id, refresh_token, scope)
        is_valid_refresh_token = data is not None

        # Return proper error responses on invalid conditions
        if not (is_valid_client_id and is_valid_client_secret):
            return self._make_json_error_response('invalid_client')

        if not is_valid_scope:
            return self._make_json_error_response('invalid_scope')

        if not is_valid_refresh_token:
            return self._make_json_error_response('invalid_grant')

        # Discard original refresh token
        self.discard_refresh_token(client_id, refresh_token)

        # Generate access tokens once all conditions have been met
        access_token = self.generate_access_token()
        token_type = self.token_type
        expires_in = self.token_expires_in
        refresh_token = self.generate_refresh_token()

        # Save information to be used to validate later requests
        self.persist_token_information(client_id=client_id,
                                       scope=scope,
                                       access_token=access_token,
                                       token_type=token_type,
                                       expires_in=expires_in,
                                       refresh_token=refresh_token,
                                       data=data)

        # Return json response
        return self._make_json_response({
            'access_token': access_token,
            'token_type': token_type,
            'expires_in': expires_in,
            'refresh_token': refresh_token
        })

def refresh_token ( self , grant_type , client_id , client_secret , refresh_token , ** params ) : if grant_type != 'refresh_token' : return self . _make_json_error_response ( 'unsupported_grant_type' ) is_valid_client_id = self . validate_client_id ( client_id ) is_valid_client_secret = self . validate_client_secret ( client_id , client_secret ) scope = params . get ( 'scope' , '' ) is_valid_scope = self . validate_scope ( client_id , scope ) data = self . from_refresh_token ( client_id , refresh_token , scope ) is_valid_refresh_token = data is not None if not ( is_valid_client_id and is_valid_client_secret ) : return self . _make_json_error_response ( 'invalid_client' ) if not is_valid_scope : return self . _make_json_error_response ( 'invalid_scope' ) if not is_valid_refresh_token : return self . _make_json_error_response ( 'invalid_grant' ) self . discard_refresh_token ( client_id , refresh_token ) access_token = self . generate_access_token ( ) token_type = self . token_type expires_in = self . token_expires_in refresh_token = self . generate_refresh_token ( ) self . persist_token_information ( client_id = client_id , scope = scope , access_token = access_token , token_type = token_type , expires_in = expires_in , refresh_token = refresh_token , data = data ) return self . _make_json_response ( { 'access_token' : access_token , 'token_type' : token_type , 'expires_in' : expires_in , 'refresh_token' : refresh_token } )

Generate access token HTTP response from a refresh token .


def get_token(self,
                  grant_type,
                  client_id,
                  client_secret,
                  redirect_uri,
                  code,
                  **params):
        """Generate access token HTTP response.

        :param grant_type: Desired grant type. Must be "authorization_code".
        :type grant_type: str
        :param client_id: Client ID.
        :type client_id: str
        :param client_secret: Client secret.
        :type client_secret: str
        :param redirect_uri: Client redirect URI.
        :type redirect_uri: str
        :param code: Authorization code.
        :type code: str
        :rtype: requests.Response
        """

        # Ensure proper grant_type
        if grant_type != 'authorization_code':
            return self._make_json_error_response('unsupported_grant_type')

        # Check conditions
        is_valid_client_id = self.validate_client_id(client_id)
        is_valid_client_secret = self.validate_client_secret(client_id,
                                                             client_secret)
        is_valid_redirect_uri = self.validate_redirect_uri(client_id,
                                                           redirect_uri)

        scope = params.get('scope', '')
        is_valid_scope = self.validate_scope(client_id, scope)
        data = self.from_authorization_code(client_id, code, scope)
        is_valid_grant = data is not None

        # Return proper error responses on invalid conditions
        if not (is_valid_client_id and is_valid_client_secret):
            return self._make_json_error_response('invalid_client')

        if not is_valid_grant or not is_valid_redirect_uri:
            return self._make_json_error_response('invalid_grant')

        if not is_valid_scope:
            return self._make_json_error_response('invalid_scope')

        # Discard original authorization code
        self.discard_authorization_code(client_id, code)

        # Generate access tokens once all conditions have been met
        access_token = self.generate_access_token()
        token_type = self.token_type
        expires_in = self.token_expires_in
        refresh_token = self.generate_refresh_token()

        # Save information to be used to validate later requests
        self.persist_token_information(client_id=client_id,
                                       scope=scope,
                                       access_token=access_token,
                                       token_type=token_type,
                                       expires_in=expires_in,
                                       refresh_token=refresh_token,
                                       data=data)

        # Return json response
        return self._make_json_response({
            'access_token': access_token,
            'token_type': token_type,
            'expires_in': expires_in,
            'refresh_token': refresh_token
        })

def get_token ( self , grant_type , client_id , client_secret , redirect_uri , code , ** params ) : if grant_type != 'authorization_code' : return self . _make_json_error_response ( 'unsupported_grant_type' ) is_valid_client_id = self . validate_client_id ( client_id ) is_valid_client_secret = self . validate_client_secret ( client_id , client_secret ) is_valid_redirect_uri = self . validate_redirect_uri ( client_id , redirect_uri ) scope = params . get ( 'scope' , '' ) is_valid_scope = self . validate_scope ( client_id , scope ) data = self . from_authorization_code ( client_id , code , scope ) is_valid_grant = data is not None if not ( is_valid_client_id and is_valid_client_secret ) : return self . _make_json_error_response ( 'invalid_client' ) if not is_valid_grant or not is_valid_redirect_uri : return self . _make_json_error_response ( 'invalid_grant' ) if not is_valid_scope : return self . _make_json_error_response ( 'invalid_scope' ) self . discard_authorization_code ( client_id , code ) access_token = self . generate_access_token ( ) token_type = self . token_type expires_in = self . token_expires_in refresh_token = self . generate_refresh_token ( ) self . persist_token_information ( client_id = client_id , scope = scope , access_token = access_token , token_type = token_type , expires_in = expires_in , refresh_token = refresh_token , data = data ) return self . _make_json_response ( { 'access_token' : access_token , 'token_type' : token_type , 'expires_in' : expires_in , 'refresh_token' : refresh_token } )


def get_authorization_code_from_uri(self, uri):
        """Get authorization code response from a URI. This method will
        ignore the domain and path of the request, instead
        automatically parsing the query string parameters.

        :param uri: URI to parse for authorization information.
        :type uri: str
        :rtype: requests.Response
        """
        params = utils.url_query_params(uri)
        try:
            if 'response_type' not in params:
                raise TypeError('Missing parameter response_type in URL query')

            if 'client_id' not in params:
                raise TypeError('Missing parameter client_id in URL query')

            if 'redirect_uri' not in params:
                raise TypeError('Missing parameter redirect_uri in URL query')

            return self.get_authorization_code(**params)
        except TypeError as exc:
            self._handle_exception(exc)

            # Catch missing parameters in request
            err = 'invalid_request'
            if 'redirect_uri' in params:
                u = params['redirect_uri']
                return self._make_redirect_error_response(u, err)
            else:
                return self._invalid_redirect_uri_response()
        except StandardError as exc:
            self._handle_exception(exc)

            # Catch all other server errors
            err = 'server_error'
            u = params['redirect_uri']
            return self._make_redirect_error_response(u, err)

Get authorization code response from a URI . This method will ignore the domain and path of the request instead automatically parsing the query string parameters .


def get_token_from_post_data(self, data):
        """Get a token response from POST data.

        :param data: POST data containing authorization information.
        :type data: dict
        :rtype: requests.Response
        """
        try:
            # Verify OAuth 2.0 Parameters
            for x in ['grant_type', 'client_id', 'client_secret']:
                if not data.get(x):
                    raise TypeError("Missing required OAuth 2.0 POST param: {0}".format(x))

            # Handle get token from refresh_token
            if 'refresh_token' in data:
                return self.refresh_token(**data)

            # Handle get token from authorization code
            for x in ['redirect_uri', 'code']:
                if not data.get(x):
                    raise TypeError("Missing required OAuth 2.0 POST param: {0}".format(x))
            return self.get_token(**data)
        except TypeError as exc:
            self._handle_exception(exc)

            # Catch missing parameters in request
            return self._make_json_error_response('invalid_request')
        except StandardError as exc:
            self._handle_exception(exc)

            # Catch all other server errors
            return self._make_json_error_response('server_error')


def get_authorization(self):
        """Get authorization object representing status of authentication."""
        auth = self.authorization_class()
        header = self.get_authorization_header()
        if not header or not header.split:
            return auth
        header = header.split()
        if len(header) > 1 and header[0] == 'Bearer':
            auth.is_oauth = True
            access_token = header[1]
            self.validate_access_token(access_token, auth)
            if not auth.is_valid:
                auth.error = 'access_denied'
        return auth

def get_authorization ( self ) : auth = self . authorization_class ( ) header = self . get_authorization_header ( ) if not header or not header . split : return auth header = header . split ( ) if len ( header ) > 1 and header [ 0 ] == 'Bearer' : auth . is_oauth = True access_token = header [ 1 ] self . validate_access_token ( access_token , auth ) if not auth . is_valid : auth . error = 'access_denied' return auth

Get authorization object representing status of authentication .


def open(self, bus):
        """Open the smbus interface on the specified bus."""
        # Close the device if it's already open.
        if self._device is not None:
            self.close()
        # Try to open the file for the specified bus.  Must turn off buffering
        # or else Python 3 fails (see: https://bugs.python.org/issue20074)
        self._device = open('/dev/i2c-{0}'.format(bus), 'r+b', buffering=0)

def open ( self , bus ) : if self . _device is not None : self . close ( ) self . _device = open ( '/dev/i2c-{0}' . format ( bus ) , 'r+b' , buffering = 0 )

Open the smbus interface on the specified bus .


def read_byte(self, addr):
        """Read a single byte from the specified device."""
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        self._select_device(addr)
        return ord(self._device.read(1))

Read a single byte from the specified device .


def read_bytes(self, addr, number):
        """Read many bytes from the specified device."""
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        self._select_device(addr)
        return self._device.read(number)

Read many bytes from the specified device .


def read_byte_data(self, addr, cmd):
        """Read a single byte from the specified cmd register of the device."""
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        # Build ctypes values to marshall between ioctl and Python.
        reg = c_uint8(cmd)
        result = c_uint8()
        # Build ioctl request.
        request = make_i2c_rdwr_data([
            (addr, 0, 1, pointer(reg)),             # Write cmd register.
            (addr, I2C_M_RD, 1, pointer(result))    # Read 1 byte as result.
        ])
        # Make ioctl call and return result data.
        ioctl(self._device.fileno(), I2C_RDWR, request)
        return result.value

Read a single byte from the specified cmd register of the device .


def write_bytes(self, addr, buf):
        """Write many bytes to the specified device. buf is a bytearray"""
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        self._select_device(addr)
        self._device.write(buf)

Write many bytes to the specified device . buf is a bytearray


def write_byte_data(self, addr, cmd, val):
        """Write a byte of data to the specified cmd register of the device.
        """
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        # Construct a string of data to send with the command register and byte value.
        data = bytearray(2)
        data[0] = cmd & 0xFF
        data[1] = val & 0xFF
        # Send the data to the device.
        self._select_device(addr)
        self._device.write(data)

Write a byte of data to the specified cmd register of the device .


def write_i2c_block_data(self, addr, cmd, vals):
        """Write a buffer of data to the specified cmd register of the device.
        """
        assert self._device is not None, 'Bus must be opened before operations are made against it!'
        # Construct a string of data to send, including room for the command register.
        data = bytearray(len(vals)+1)
        data[0] = cmd & 0xFF  # Command register at the start.
        data[1:] = vals[0:]   # Copy in the block data (ugly but necessary to ensure
                              # the entire write happens in one transaction).
        # Send the data to the device.
        self._select_device(addr)
        self._device.write(data)

Write a buffer of data to the specified cmd register of the device .


def cdn_url(self):
        """Returns file's CDN url.

        Usage example::

            >>> file_ = File('a771f854-c2cb-408a-8c36-71af77811f3b')
            >>> file_.cdn_url
            https://ucarecdn.com/a771f854-c2cb-408a-8c36-71af77811f3b/

        You can set default effects::

            >>> file_.default_effects = 'effect/flip/-/effect/mirror/'
            >>> file_.cdn_url
            https://ucarecdn.com/a771f854-c2cb-408a-8c36-71af77811f3b/-/effect/flip/-/effect/mirror/

        """
        return '{cdn_base}{path}'.format(cdn_base=conf.cdn_base,
                                         path=self.cdn_path(self.default_effects))

def cdn_url ( self ) : return '{cdn_base}{path}' . format ( cdn_base = conf . cdn_base , path = self . cdn_path ( self . default_effects ) )


def copy(self, effects=None, target=None):
        """Creates a File Copy on Uploadcare or Custom Storage.

        File.copy method is deprecated and will be removed in 4.0.0.
        Please use `create_local_copy` and `create_remote_copy` instead.

        Args:
            - effects:
                Adds CDN image effects. If ``self.default_effects`` property
                is set effects will be combined with default effects.
            - target:
                Name of a custom storage connected to your project.
                Uploadcare storage is used if target is absent.

        """
        warning = """File.copy method is deprecated and will be
            removed in 4.0.0.
            Please use `create_local_copy`
            and `create_remote_copy` instead.
        """
        logger.warn('API Warning: {0}'.format(warning))

        if target is not None:
            return self.create_remote_copy(target, effects)
        else:
            return self.create_local_copy(effects)

def
copy
(
self
,
effects
=
,
target
=
)
:
warning
=
logger
.
warn
(
'API Warning: {0}'
.
format
(
warning
)
)
if
target
is
not
:
return
self
.
create_remote_copy
(
target
,
effects
)
else
:
return
self
.
create_local_copy
(
effects
)

Creates a File Copy on Uploadcare or Custom Storage . File . copy method is deprecated and will be removed in 4 . 0 . 0 . Please use create_local_copy and create_remote_copy instead .


def create_local_copy(self, effects=None, store=None):
        """Creates a Local File Copy on Uploadcare Storage.

        Args:
            - effects:
                Adds CDN image effects. If ``self.default_effects`` property
                is set effects will be combined with default effects.
            - store:
                If ``store`` option is set to False the copy of your file will
                be deleted in 24 hour period after the upload.
                Works only if `autostore` is enabled in the project.

        """
        effects = self._build_effects(effects)
        store = store or ''
        data = {
            'source': self.cdn_path(effects)
        }
        if store:
            data['store'] = store
        return rest_request('POST', 'files/', data=data)

def create_local_copy ( self , effects = None , store = None ) : effects = self . _build_effects ( effects ) store = store or '' data = { 'source' : self . cdn_path ( effects ) } if store : data [ 'store' ] = store return rest_request ( 'POST' , 'files/' , data = data )

Creates a Local File Copy on Uploadcare Storage .


def create_remote_copy(self, target, effects=None, make_public=None,
                           pattern=None):
        """Creates file copy in remote storage.

        Args:
            - target:
                Name of a custom storage connected to the project.
            - effects:
                Adds CDN image effects to ``self.default_effects`` if any.
            - make_public:
                To forbid public from accessing your files on the storage set
                ``make_public`` option to be False.
                Default value is None. Files have public access by default.
            - pattern:
                Specify ``pattern`` option to set S3 object key name.
                Takes precedence over pattern set in project settings.
                If neither is specified defaults to
                `${uuid}/${filename}${effects}${ext}`.

        For more information on each of the options above please refer to
        REST API docs https://uploadcare.com/docs/api_reference/rest/accessing_files/.

        Following example copies a file to custom storage named ``samplefs``:

             >>> file = File('e8ebfe20-8c11-4a94-9b40-52ecad7d8d1a')
             >>> file.create_remote_copy(target='samplefs',
             >>>                         make_public=True,
             >>>                         pattern='${uuid}/${filename}${ext}')

        Now custom storage ``samplefs`` contains publicly available file
        with original filename billmurray.jpg in
        in the directory named ``e8ebfe20-8c11-4a94-9b40-52ecad7d8d1a``.

        """
        effects = self._build_effects(effects)
        data = {
            'source': self.cdn_path(effects),
            'target': target
        }

        if make_public is not None:
            data['make_public'] = make_public
        if pattern is not None:
            data['pattern'] = pattern
        return rest_request('POST', 'files/', data=data)

def create_remote_copy ( self , target , effects = None , make_public = None , pattern = None ) : effects = self . _build_effects ( effects ) data = { 'source' : self . cdn_path ( effects ) , 'target' : target } if make_public is not None : data [ 'make_public' ] = make_public if pattern is not None : data [ 'pattern' ] = pattern return rest_request ( 'POST' , 'files/' , data = data )


def construct_from(cls, file_info):
        """Constructs ``File`` instance from file information.

        For example you have result of
        ``/files/1921953c-5d94-4e47-ba36-c2e1dd165e1a/`` API request::

            >>> file_info = {
                    # ...
                    'uuid': '1921953c-5d94-4e47-ba36-c2e1dd165e1a',
                    # ...
                }
            >>> File.construct_from(file_info)
            <uploadcare.File 1921953c-5d94-4e47-ba36-c2e1dd165e1a>

        """
        file_ = cls(file_info['uuid'])
        file_.default_effects = file_info.get('default_effects')
        file_._info_cache = file_info
        return file_

Constructs File instance from file information .


def upload(cls, file_obj, store=None):
        """Uploads a file and returns ``File`` instance.

        Args:
            - file_obj: file object to upload to
            - store (Optional[bool]): Should the file be automatically stored
                upon upload. Defaults to None.
                - False - do not store file
                - True - store file (can result in error if autostore
                               is disabled for project)
                - None - use project settings

        Returns:
            ``File`` instance

        """
        if store is None:
            store = 'auto'
        elif store:
            store = '1'
        else:
            store = '0'

        data = {
            'UPLOADCARE_STORE': store,
        }

        files = uploading_request('POST', 'base/', data=data,
                                  files={'file': file_obj})
        file_ = cls(files['file'])
        return file_

def upload ( cls , file_obj , store = None ) : if store is None : store = 'auto' elif store : store = '1' else : store = '0' data = { 'UPLOADCARE_STORE' : store , } files = uploading_request ( 'POST' , 'base/' , data = data , files = { 'file' : file_obj } ) file_ = cls ( files [ 'file' ] ) return file_

Uploads a file and returns File instance .


def upload_from_url(cls, url, store=None, filename=None):
        """Uploads file from given url and returns ``FileFromUrl`` instance.

        Args:
            - url (str): URL of file to upload to
            - store (Optional[bool]): Should the file be automatically stored
                upon upload. Defaults to None.
                - False - do not store file
                - True - store file (can result in error if autostore
                               is disabled for project)
                - None - use project settings
            - filename (Optional[str]): Name of the uploaded file. If this not
                specified the filename will be obtained from response headers
                or source URL. Defaults to None.

        Returns:
            ``FileFromUrl`` instance

        """
        if store is None:
            store = 'auto'
        elif store:
            store = '1'
        else:
            store = '0'

        data = {
            'source_url': url,
            'store': store,
        }
        if filename:
            data['filename'] = filename

        result = uploading_request('POST', 'from_url/',
                                   data=data)
        if 'token' not in result:
            raise APIError(
                'could not find token in result: {0}'.format(result)
            )
        file_from_url = cls.FileFromUrl(result['token'])
        return file_from_url

def
upload_from_url
(
cls
,
url
,
store
=
,
filename
=
)
:
if
store
is
:
store
=
'auto'
elif
store
:
store
=
'1'
else
:
store
=
'0'
data
=
{
'source_url'
:
url
,
'store'
:
store
,
}
if
filename
:
data
[
'filename'
]
=
filename
result
=
uploading_request
(
'POST'
,
'from_url/'
,
data
=
data
)
if
'token'
not
in
result
:
raise
APIError
(
'could not find token in result: {0}'
.
format
(
result
)
)
file_from_url
=
cls
.
FileFromUrl
(
result
[
'token'
]
)
return
file_from_url

Uploads file from given url and returns FileFromUrl instance .


def upload_from_url_sync(cls, url, timeout=30, interval=0.3,
                             until_ready=False, store=None, filename=None):
        """Uploads file from given url and returns ``File`` instance.

        Args:
            - url (str): URL of file to upload to
            - store (Optional[bool]): Should the file be automatically stored
                upon upload. Defaults to None.
                - False - do not store file
                - True - store file (can result in error if autostore
                               is disabled for project)
                - None - use project settings
            - filename (Optional[str]): Name of the uploaded file. If this not
                specified the filename will be obtained from response headers
                or source URL. Defaults to None.
            - timeout (Optional[int]): seconds to wait for successful upload.
                Defaults to 30.
            - interval (Optional[float]): interval between upload status checks.
                Defaults to 0.3.
            - until_ready (Optional[bool]): should we wait until file is
                available via CDN. Defaults to False.

        Returns:
            ``File`` instance

        Raises:
            ``TimeoutError`` if file wasn't uploaded in time

        """
        ffu = cls.upload_from_url(url, store, filename)
        return ffu.wait(timeout=timeout, interval=interval,
                        until_ready=until_ready)

def upload_from_url_sync ( cls , url , timeout = 30 , interval = 0.3 , until_ready = False , store = None , filename = None ) : ffu = cls . upload_from_url ( url , store , filename ) return ffu . wait ( timeout = timeout , interval = interval , until_ready = until_ready )

Uploads file from given url and returns File instance .


def file_cdn_urls(self):
        """Returns CDN urls of all files from group without API requesting.

        Usage example::

            >>> file_group = FileGroup('0513dda0-582f-447d-846f-096e5df9e2bb~2')
            >>> file_group.file_cdn_urls[0]
            'https://ucarecdn.com/0513dda0-582f-447d-846f-096e5df9e2bb~2/nth/0/'

        """
        file_cdn_urls = []
        for file_index in six.moves.xrange(len(self)):
            file_cdn_url = '{group_cdn_url}nth/{file_index}/'.format(
                group_cdn_url=self.cdn_url,
                file_index=file_index
            )
            file_cdn_urls.append(file_cdn_url)
        return file_cdn_urls

def file_cdn_urls ( self ) : file_cdn_urls = [ ] for file_index in six . moves . xrange ( len ( self ) ) : file_cdn_url = '{group_cdn_url}nth/{file_index}/' . format ( group_cdn_url = self . cdn_url , file_index = file_index ) file_cdn_urls . append ( file_cdn_url ) return file_cdn_urls

Returns CDN urls of all files from group without API requesting .


def construct_from(cls, group_info):
        """Constructs ``FileGroup`` instance from group information."""
        group = cls(group_info['id'])
        group._info_cache = group_info
        return group

def construct_from ( cls , group_info ) : group = cls ( group_info [ 'id' ] ) group . _info_cache = group_info return group

Constructs FileGroup instance from group information .


def create(cls, files):
        """Creates file group and returns ``FileGroup`` instance.

        It expects iterable object that contains ``File`` instances, e.g.::

            >>> file_1 = File('6c5e9526-b0fe-4739-8975-72e8d5ee6342')
            >>> file_2 = File('a771f854-c2cb-408a-8c36-71af77811f3b')
            >>> FileGroup.create((file_1, file_2))
            <uploadcare.FileGroup 0513dda0-6666-447d-846f-096e5df9e2bb~2>

        """
        data = {}
        for index, file_ in enumerate(files):
            if isinstance(file_, File):
                file_index = 'files[{index}]'.format(index=index)
                data[file_index] = six.text_type(file_)
            else:
                raise InvalidParamError(
                    'all items have to be ``File`` instance'
                )
        if not data:
            raise InvalidParamError('set of files is empty')

        group_info = uploading_request('POST', 'group/', data=data)

        group = cls.construct_from(group_info)
        return group

Creates file group and returns FileGroup instance .