lnk package

lnk.abstract module

Includes the base-class for all commands of any service.

class lnk.abstract.AbstractCommand(service, command)[source]

Bases: object

Abstract-base-class for all commands of any service.

This class’ constructor handles the bulk of configuration every command needs, such as fetching the service’s API url, available endpoints and default settings. It also gives each command a queue and lock for threading, as well as a few other things most, if not all, commands need. The class defines an interface all commands must have, with some of AbstractCommand’s methods, such as fetch(), not being implemented and throwing a NotImplementedError if called directly. An AbstractCommand must have knowledge about the service that the class subclassing it uses (e.g. bit.ly or tinyurl), as well as about the name of the command (e.g. ‘link’ or ‘stats’).

url

str

The URL of the API.

api

str

The URL of the API, joined with its version. Endpoints can be joined to this string to form a full URL (without parameters) for a request.

config

dict

The configuration data of a command.

endpoints

dict

The endpoints for a command.

settings

dict

The default settings of a command.

sets

dict|None

If available, the data sets/categories that the command allows, else None if the command has no such thing (e.g. the ‘link’ command).

queue

Queue.Queue

A queue for thread-safe data-passing.

lock

threading.Lock

A lock object for thread-safe actions.

error

Exception

The last exception thrown by a thread started with the new_thread method. This is useful to see if a thread threw an exception which would otherwise not be properly handled (because you can’t catch exceptions from a child-thread in the main thread).

parameters

dict

Dictionary for the parameters of an HTTP request.

list_item

str

A string, formatted with ecstasy, that should be used to format a list-item (e.g. for the stats command). It already includes the necessary markup such that str.format() can be used on it directly with the string to be formatted.

fetch(*args)[source]

Abstract method to fetch command-specific data.

Parameters:args (variadic) – Whatever arguments the overriden method takes.
Raises:NotImplementedError – When called directly.
get(endpoint, parameters=None)[source]

Base method to perform an HTTP request with the GET method.

Parameters:
  • endpoint (str) – The endpoint at which to request data.
  • parameters (dict) – Additional parameters to pass with the request.
Returns:

The requests.Response object resulting from the request.

join(threads, timeout=120)[source]

Joins a list of thread and checks for errors.

Each thread is join with a timeout period as specified by the timeout parameter of this function. If an error was found in the ‘error’ attribute, it is re-raised so that it can be caught in the main thread.

Parameters:
  • threads (list) – The list of threading.Threads to join.
  • timeout (float) – A floating-point number specifying the number of seconds to wait when joining. Defaults to 60 seconds.
Raises:
  • lnk.errors.InternalError – If a thread could not be joined in the given timeout period (i.e. if it is still alive after joining).
  • Other errors – If a thread threw an exception, this exception is re-raised in the main thread.
new_thread(function, *args, **kwargs)[source]

Runs a function in a new thread and returns the thread.

The function is run in a new thread in way that all positional and keyword arguments can be forwarded to the function. Additionally, extra measures are taken to wrap the function into another proxy function that handles exceptions which would otherwise not be handled. If the function to be called throws an exception, this is recorded and the exception is assigned to ‘error’ attribute, where it can later be checked.

Parameters:
  • function (func) – The function to execute.
  • args (variadic) – The positional arguments to pass to the function when calling it.
  • kwargs (variadic) – The keyword arguments to pass to the function when calling it.
Returns:

The started (!) thread in which the function is being executed.

post(endpoint, authorization=None, data=None)[source]

Base method to perform an HTTP request with the POST method.

Parameters:
  • endpoint (str) – The endpoint at which to send data.
  • authorization (tuple) – Optionally, a (login, password) tuple that should be used for HTTP authorization.
  • data (dict) – Optionally, data to send with the request.
Returns:

The requests.Response object resulting from the request.

lnk.abstract.filter_sets(all_sets, only, hide)[source]

Filters a set of categories.

This method is used by many commands that use some sort of dictionary of available data sets/categories, which must filter those sets according to the ones the user wants to have included in the response by that command.

Parameters:
  • all_sets (dict) – The base dictionary of all available sets (from which a subset should be filtered).
  • only (tuple) – A tuple of the names of the categories/sets to include.
  • hide (tuple) – A tuple of the names of the categories/sets to exclude. Note that sets are hidden after the ‘only’ sets have been processed, i.e. if a certain set is in ‘only’ and in ‘hide’, it will first be selected and then discared again (which would make no sense). Usually either ‘only’ or ‘hide’ is empty.
Returns:

A dictionary containing the filtered key/value pairs.

lnk.beauty module

Data beautification.

class lnk.beauty.Line(raw, escaped)

Bases: tuple

__getnewargs__()

Return self as a plain tuple. Used by copy and pickle.

__getstate__()

Exclude the OrderedDict from pickling

__repr__()

Return a nicely formatted representation string

escaped

Alias for field number 1

raw

Alias for field number 0

lnk.beauty.boxify(results)[source]

Formats results of command into a box.

Parameters:results (list) – A list of results, where each result is a list of lines (e.g. all the lines for the statistics of one URL).
Returns:The results in a pretty box, as a string.
lnk.beauty.escape(line)[source]

Escapes a raw string.

Parameters:line (str) – The raw string to escape.
Returns:A beauty.Line object with the original raw component and the same string, but escaped, i.e. without the formatting codes applied by ecstasy – only the text.
lnk.beauty.get_escaped(results)[source]

Gets escaped lines for the results passed to boxify().

Parameters:results (list) – The results passed to boxify().
Returns:A list of beauty.Line objects with a raw and escaped component.
lnk.beauty.ljust(line, width, padding=u' ')[source]

Adds space-padding to the right of a line.

ljust won’t do because of the escaped/raw thing.

Parameters:
  • line (str) – The line to adjust.
  • width (int) – The minimum width the string must have after this function.
  • padding (str) – Optionally, the string with which to pad (usually ‘ ‘).
Returns:

The adjusted raw line.

lnk.beauty.wrap(line, width, indent=None)[source]

Wraps a line to a certain width.

Why not textwrap.wrap? Because in this special situation it is necessary to wrap not only the escaped, plain-text string but at the same time also the raw string containing escape codes, which, however, should not count towards the length of a string. This method essentially wraps the plain-text string, while at the same time moving also through the raw string, but skipping escape-character-sequences when counting characters.

Parameters:
  • line (beauty.Line) – The beauty.Line object to wrap.
  • width (int) – The width to which to wrap.
  • indent (str) – An indent string with which to indent all lines after the first wrapped one.

lnk.cli module

The main entry-point to lnk from the command-line.

class lnk.cli.Main[source]

Bases: click.core.MultiCommand

The main command-group of the lnk application.

This class exists because the necessary subcommands of lnk (i.e. the commands for the services, such as bitly or googl) live in other files and click does not handle that well. There is no way to register commands from other files, so this class, which derives from click.MultiCommand, must dynamically load and compile the files in which the other commands live and extract the necessary functions so that click can execute each subcommand as if it lived in this file. It also handles argument forwarding and some string-handling (e..g so that googl and goo.gl both mean the same thing from the CLI). Its all a bit of a hack.

commands

dict

A mapping between the names of commands and their respective functions.

default

str

The name of the default service (e.g. ‘bitly’).

format_usage(context, *args)[source]
get_command(context, name)[source]

Returns the function for a given subcommand-name.

static get_function(service)[source]

Returns the ‘main’ command-function for a given service.

Parameters:service (str) – The name of the service (e.g. tinyurl).
Returns:The main() function of that service (retrieved from lnk.<service>.cli).
invoke(context)[source]

Invokes a command.

This method does some argument pre-processing, such as inserting the name of the default command if no other command was specified. It also handles the problem of dots in the names of commands (e.g. goo.gl and gool).

list_commands(context)[source]

Returns the names of all available subcommands.

lnk.cli.get_verbosity(count, level)[source]

Returns the appropriate verbosity level.

Defined here for use by all cli modules (e.g. bitly.cli).

Parameters:
  • count (int) – The verbosity count (from the -vvv flags).
  • level (int) – The verbosity level (from the –level flag).
Returns:

The default verbosity if both count and level are zero, else the level and only if the level is also zero, the count.

lnk.cli.main()[source]

Insantiates a Main object and executes it.

The ‘standalone_mode’ is so that click doesn’t handle usage-exceptions itself, but bubbles them up.

Parameters:args (tuple) – The command-line arguments.

lnk.countries module

A mapping between short ISO abbreviations for countries and their full names.

lnk.errors module

Custom error classes + error handling and warning mechanisms.

All non-standard errors raised by lnk should be defined here.

exception lnk.errors.APIError(what, message=None, **additional)[source]

Bases: lnk.errors.Error

Raised if there was a problem communicating with the API.

Meaning if the problem was not ill-formed data as is the case for an HTTPError, but something specific to the API (possibly associated with its key/access-token).

exception lnk.errors.AuthorizationError(service, what='Missing authorization code!', **additional)[source]

Bases: lnk.errors.Error

Raised in case of an authorization error.

This is mostly the case initially, when the user first runs lnk and has noet yet authenticated himself and authorized lnk to access private information (such as user data for bitly).

class lnk.errors.Catch(verbosity=0, usage=None, service=None)[source]

Bases: object

Exception-handling class.

Catch is essentially a interface to its main method ‘catch’, but adds the ability to add a usage string that is displayed optionally in case of a UsageError, and also the service being used while the exception is thrown. The information about the url-shortening service is of use for ConnectionErrors.

verbosity

int

The verbosity level (defaults to 0).

usage

str

Optionally, a usage string to display for UsageErrors.

service

str

The url-shortening service currently in use.

catch(function, *args, **kwargs)[source]

Executes a function and handles any potential exceptions.

Parameters:
  • function (func) – The function to execute.
  • args (variadic) – The positional arguments to pass to the function call.
  • kwargs (variadic) – The keyword arguments to pass to the function call.
static get_error()[source]

Retrieves the last error raised in the system.

handle_error()[source]

Handles an Error.

Takes care of retrieveing the error message string from the Error that is appropriate to the verbosity level passed to the constructor of Catch. This message string is then printed to stdout. If the Error was a UsageError, the usage string is printed too.

static handle_google_error()[source]

Handles exceptions raised by the goo.gl api client.

Exceptions raised by the goo.gl api client do not make any error clean message available, but only a long, formatted string ready for output. This method takes care of retrieving the actualy ‘reason’ for the exception via regular expressions. This reason is then re-raised as an HTTPError that can be handled by Catch.

exception lnk.errors.ConnectionError(what, hint=None, **additional)[source]

Bases: lnk.errors.Error

Raised if there was a problem connecting with the API.

(Usually if the user is not connected to the interwebs).

exception lnk.errors.Error(what, **additional)[source]

Bases: exceptions.Exception

Exception base class for all errors.

Implements a system of multiple verbosity levels such that error output can be controlled according to the verbosity setting specified by the user (how many -v are passed).

what

str

A plain string message specifying what happened.

levels

list

A list of strings for each verbosity level.

static get_levels(additional)[source]

Transforms and formats error levels.

Each additional level passed to the constructor of Error is either the error string, in which case its level is 1 or a Error.Message tuple consisting of that same error string and additionally an integer specifying the level. This information is parsed here, such that the result is a list of level strings. Moreover, each key/value pair of each error message is formatted with ecstasy to make it look pretty.

Parameters:additional (dict) – The additional error messages.
Returns:A list of strings for each level of verbosity.
level(verbosity)[source]

Fetches a list of all non-empty levels for a given verbosity.

Parameters:verbosity (int) – The verbosity level (e.g. 0 for ‘what’).
Returns:All levels for the given verbosity, but filtering out empty ones.
exception lnk.errors.HTTPError(what, code=None, status=None, **additional)[source]

Bases: lnk.errors.Error

Raised in case of a faulty HTTP request.

Usually because the data provided by the user was ill-formed (such as an expanded url where a shortened one is expected). Additionally may have a code and status information.

exception lnk.errors.InternalError(what, **additional)[source]

Bases: lnk.errors.Error

Raised when something went wrong internally.

Will be thrown only within methods that are non-accessible via the API but are used forinternal features or processing. Basically get mad at the project creator.

exception lnk.errors.InvalidKeyError(what, **additional)[source]

Bases: lnk.errors.Error

Raised when an invalid key is passed to the config command.

class lnk.errors.Message(what, level)

Bases: tuple

__getnewargs__()

Return self as a plain tuple. Used by copy and pickle.

__getstate__()

Exclude the OrderedDict from pickling

__repr__()

Return a nicely formatted representation string

level

Alias for field number 1

what

Alias for field number 0

exception lnk.errors.UsageError(what, **additional)[source]

Bases: lnk.errors.Error

Raised for invalid command-line usage.

A UsageError is raised by lnk if some cli-related badness is not handled by click (such as misisng urls). If invalid command-line usage is handled by click, this is detected and click’s exception is then re-raised as a UsageError (i.e. any faulty cli input is always reported as an error of this type).

lnk.errors.catch(function, *args, **kwargs)[source]

Convenience function for a Catch object with default settings.

Parameters:
  • function (func) – The function to execute.
  • args (variadic) – The positional arguments to pass to the function call.
  • kwargs (variadic) – The keyword arguments to pass to the function call.
lnk.errors.warn(what)[source]

Outputs and formats a warning.

Parameters:what (str) – The warning string to output.