Decorators

The method decorators detailed in this section describe request properties that are relevant to all invocations of a consumer method.

headers

class uplink.headers(arg, **kwargs)

A decorator that adds static headers for API calls.

@headers({"User-Agent": "Uplink-Sample-App})
@get("/user")
def get_user(self):
    """Get the current user"""

When used as a class decorator, headers applies to all consumer methods bound to the class:

@headers({"Accept": "application/vnd.github.v3.full+json")
class GitHub(Consumer):
    ...

headers takes the same arguments as dict.

Parameters:
  • *arg – A dict containing header values.
  • **kwargs – More header values.

json

class uplink.json

Use as a decorator to make JSON requests.

You can annotate a method argument with uplink.Body, which indicates that the argument’s value should become the request’s body. uplink.Body has to be either a dict or a subclass of py:class:collections.Mapping.

Example

@json
@patch(/user")
def update_user(self, **info: Body):
    """Update the current user."""

You can alternatively use the uplink.Field annotation to specify JSON fields separately, across multiple arguments:

Example: .. code-block:: python

@json @patch(/user”) def update_user(self, name: Field, email: Field(“e-mail”):

“”“Update the current user.”“”

Further, to set a nested field, you can specify the path of the target field with a tuple of strings as the first argument of uplink.Field.

Example

Consider a consumer method that sends a PATCH request with a JSON body of the following format:

{
    user: {
        name: "<User's Name>"
    },
}

The tuple ("user", "name") specifies the path to the highlighted inner field:

@json
@patch(/user")
def update_user(
                self,
                new_name: Field(("user", "name"))
):
    """Update the current user."""

form_url_encoded

class uplink.form_url_encoded

URL-encodes the request body.

Used on POST/PUT/PATCH request. It url-encodes the body of the message and sets the appropriate Content-Type header. Further, each field argument should be annotated with uplink.Field.

Example

@form_url_encoded
@post("/users/edit")
def update_user(self, first_name: Field, last_name: Field):
    """Update the current user."""

multipart

class uplink.multipart

Sends multipart form data.

Multipart requests are commonly used to upload files to a server. Further, annotate each part argument with Part.

Example

@multipart
@put(/user/photo")
def update_user(self, photo: Part, description: Part):
    """Upload a user profile photo."""

timeout

class uplink.timeout(seconds)

Time to wait for a server response before giving up.

When used on other decorators it specifies how long (in secs) a decorator should wait before giving up.

Example

@timeout(60)
@get("/user/posts")
def get_posts(self):
    """Fetch all posts for the current users."""

When used as a class decorator, timeout applies to all consumer methods bound to the class.

Parameters:seconds (int) – An integer used to indicate how long should the request wait.

args

class uplink.args(*annotations, **more_annotations)

Annotate method arguments for Python 2.7 compatibility.

Arrange annotations in the same order as their corresponding function arguments.

Example

@args(Path, Query)
@get("/users/{username})
def get_user(self, username, visibility):
    """Get a specific user."""

Use keyword args to target specific method parameters.

Example

@args(visibility=Query)
@get("/users/{username})
def get_user(self, username, visibility):
    """Get a specific user."""
Parameters:
  • *annotations – Any number of annotations.
  • **more_annotations – More annotations, targeting specific method arguments.

response_handler

class uplink.response_handler(func)

A decorator for creating custom response handlers.

To register a function as a custom response handler, decorate the function with this class. The decorated function should accept a single positional argument, an HTTP response object:

Example

@response_handler
def raise_for_status(response):
    response.raise_for_status()
    return response

Then, to apply custom response handling to a request method, simply decorate the method with the registered response handler:

Example

@raise_for_status
@get("/user/posts")
def get_posts(self):
    """Fetch all posts for the current users."""

To apply custom response handling on all request methods of a uplink.Consumer subclass, simply decorate the class with the registered response handler:

Example

@raise_for_status
class GitHub(Consumer):
   ...

New in version 0.4.0.

error_handler

class uplink.error_handler(func)

A decorator for creating custom error handlers.

To register a function as a custom error handler, decorate the function with this class. The decorated function should accept three positional arguments: (1) the type of the exception, (2) the exception instance raised, and (3) a traceback instance.

Example

@error_handler
def raise_api_error(exc_type, exc_val, exc_tb):
    # wrap client error with custom API error
    ...

Then, to apply custom error handling to a request method, simply decorate the method with the registered error handler:

Example

@raise_api_error
@get("/user/posts")
def get_posts(self):
    """Fetch all posts for the current users."""

To apply custom error handling on all request methods of a uplink.Consumer subclass, simply decorate the class with the registered error handler:

Example

@raise_api_error
class GitHub(Consumer):
   ...

New in version 0.4.0.

Note

Error handlers can not completely suppress exceptions. The original exception is thrown if the error handler doesn’t throw anything.

inject

class uplink.inject(*hooks)

A decorator that applies one or more hooks to a request method.

Example

@inject(Query("sort").with_value("pushed"))
@get("users/{user}/repos")
def list_repos(self, user):
    """Lists user's public repos by latest pushed."""

New in version 0.4.0.

returns.*

Converting an HTTP response body into a custom Python object is straightforward with Uplink; the uplink.returns modules exposes optional decorators for defining the expected return type and data serialization format for any consumer method.

uplink.returns.from_json

alias of json

class uplink.returns.json(model=None, member=())

Specifies that the decorated consumer method should return a JSON object. If a model is provided, the resulting JSON object is converted into the model object using an appropriate converter (see uplink.loads.from_json()).

# This method will return a JSON object (e.g., a dict or list)
@returns.json
@get("/users/{username}")
def get_user(self, username):
    """Get a specific user."""

Returning a Specific JSON Field:

This decorator accepts two optional arguments. The member argument accepts a string or tuple that specifies the path of an internal field in the JSON document.

For instance, consider an API that returns JSON responses that, at the root of the document, contains both the server-retrieved data and a list of relevant API errors:

{
    "data": { "user": "prkumar", "id": 140232 },
    "errors": []
}

If returning the list of errors is unnecessary, we can use the member argument to strictly return the inner field data:

@returns.json(member="data")
@get("/users/{username}")
def get_user(self, username):
    """Get a specific user."""

Deserialize Objects from JSON:

Often, JSON responses represent models in your application. If an existing Python object encapsulates this model, use the model argument to specify it as the return type:

@returns.json(model=User)
@get("/users/{username}")
def get_user(self, username):
    """Get a specific user."""

For Python 3 users, you can alternatively provide a return value annotation. Hence, the previous code is equivalent to the following in Python 3:

@returns.json
@get("/users/{username}")
def get_user(self, username) -> User:
    """Get a specific user."""

Both usages typically require also registering a converter that knows how to deserialize the JSON into your data model object (see uplink.loads.from_json()). This step is unnecessary if these objects are defined using a library for whom Uplink has built-in support, such as marshmallow (see uplink.converters.MarshmallowConverter).

New in version v0.5.0.

class uplink.returns.model(type)

Specifies that the function returns a specific class.

In Python 3, to provide a consumer method’s return type, you can set it as the method’s return annotation:

@get("/users/{username}")
def get_user(self, username) -> UserSchema:
    """Get a specific user."""

For Python 2.7 compatibility, you can use this decorator instead:

@returns.model(UserSchema)
@get("/users/{username}")
def get_user(self, username):
    """Get a specific user."""

To have Uplink convert response bodies into the desired type, you will need to define an appropriate converter (e.g., using uplink.loads).

New in version v0.5.1.