Skip to main content

py2api

Expose python objects to external clients with minimal effort.

For the eager

py2api allows you to role out webservices (with flask) with minimal boilerplate.

To get started quickly, have a look at the examples, and play around with edits of them.

The main boilerplate here is writing code for input and output conversion. To help with this, we provide some tools. Have a look at the output_trans.py and py2rest/input_trans.py modules, especially the doctest, which should give you an idea of how to work it.

A webservice module assembled with py2api looks something like this:

from mystuff import SystemService
from py2api import OutputTrans
from py2api.py2rest import InputTransWithAttrInURL

attr_list = ["ping", "status", "stop", "start", "restart"]

name = "/api/process/"
process = WebObjWrapper(
    obj_constructor=SystemService,
    obj_constructor_arg_names=["name"],
    permissible_attr=attr_list,
    input_trans=InputTransWithAttrInURL(trans_spec=None, attr_from_url=name + "(\w+)"),
    output_trans=OutputTrans(trans_spec=None),
    name=name,
    debug=0,
)

app = add_routes_to_app(
    app, routes={process.__name__ + attr: process for attr in attr_list}
)

Note the two trans_spec=None used when making the input_trans and output_trans arguments of WebObjWrapper. There was no need to specify any special conversion there because the methods we were wrapping here only used simple types (string, int, float, list).

But often, when faced with more complex types, specifying how to carry out conversion in each and every situation constitutes a big part of the boilerplate. We provide tools to do this through a mapping (dict) separate from the code. This enables tools to be created to operate on this specification. You can specify conversion verbosely, by specifying how every argument of every function should be converted. If you're the type, you can also do so concisely, by specifying contextual rules involving the object's names and types, etc. grouping conversion rules together.

Such a (more concise) conversion specification looks like this:

from py2api.constants import _ATTR, _ARGNAME, _ELSE, _VALTYPE

def ensure_array(x):
    if not isinstance(x, ndarray):
        return array(x)
    return x

trans_spec = {
        _ATTR: {
            'this_attr': list,
            'other_attr': str,
            'yet_another_attr': {
                _VALTYPE: {
                    dict: lambda x: x
                },
                _ELSE: lambda x: {'result': x}
            }
        },
        _ARGNAME: {
            'sr': int,
            'ratio': float,
            'snips': list,
            'wf': ensure_array
        },
    }
}

See that the conversion function could be a builtin function like list, str, float, or int, or could be a custom function, declared on the fly with a lambda, or refering to a function declared elsewhere.

Motivation

Say you have some functions, classes and/or whole modules that contain some functionality that you'd like to expose as a webservice. So you grab some python libary to do that. If you make your choice right, you won't have to deal with the nitty gritty details of receiving and sending web requests. Say, you chose flask. Good choice. Known to have minimal boiler plate. So now all you have to do make a module and do something like this...

from blah import a_func_you_want_to_expose
@app.route("/a_func_you_want_to_expose/", methods=['GET'])
def _a_func_you_want_to_expose():
    # A whole bunch of boiler plate to get your arguments out
    # of the web request object, which could be in the url, the json, the data...
    # oh, and then you have to convert these all to python objects, 
    # because they're all simple types like strings, numbers and lists, 
    # you'll probably want to do some validation, perhaps add a few 
    # things that weren't really a concern of the original function, 
    # like logging, caching, providing some documentation/help, 
    # and then, oh, okay, you can call that function of yours now:

    results = a_func_you_want_to_expose(...the arguments...)

    # But wait, it's not finished! You'll need to convert these results 
    # to something that a web request can handle. Say a string or a json...

That's all. Enjoyed it?

Now do that again, and again, and again, for every fooing object you want to expose.

Still enjoy it?

We didn't. So we made py2api.

With py2api, you write the same boilerplate, but you only write it once. In py2api you specify all the concerns of the routes you want elsewhere, a bit like what OpenAPI does. But further, you have tools to reduce this specification to a set of conventions and rules that define them. For example, if you use a variable called "num" a lot, and most of the time it has to be an int, except in a few cases, your specification has to be just that. It looks like this:

This whole py2api thing wasn't only about minimizing the time spent on a boilerplate.

It's also because separation of concerns is good, and in the above example, concerns aren't as separated as they could: You have conversion, validation, logging, caching.

Also, because code reuse is good, and we don't mean copy/pasting: You probably have many arguments and types that show up in different places, and will end up writing, or copy pasting, code to handle these many times. What if you made a mistake? You'll have to find all those copies and correct them all.

Minimizing what you have to write to get something done is good: There's less places to look for bugs.

Consistency is good.

Et cetera.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py2api-0.0.4.tar.gz (39.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py2api-0.0.4-py3-none-any.whl (43.6 kB view details)

Uploaded Python 3

File details

Details for the file py2api-0.0.4.tar.gz.

File metadata

  • Download URL: py2api-0.0.4.tar.gz
  • Upload date:
  • Size: 39.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for py2api-0.0.4.tar.gz
Algorithm Hash digest
SHA256 2562545c33d60ac1307213197c67ac5298f06c506459deb4df8d1330e145e3b3
MD5 4bfefc24e6cc83327ebcc70241b91e81
BLAKE2b-256 f49b0b34e781bb73670d7cdbb66861b8a777ab2b1140060162faa797bf50c0f9

See more details on using hashes here.

File details

Details for the file py2api-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: py2api-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 43.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for py2api-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 14bd681dff86e3a571011702293c80a77926f6ac275a08f1b310100edcae6bba
MD5 013a12475100ebf807f95b57719988b1
BLAKE2b-256 c585e0b128d66e0ecc94de4f96db6ee23b1f9e4a645feca3c623c4e14e5723c5

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.5

2 files

This release

0.0.4 This release

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page