Skip to content
This repository has been archived by the owner on Jul 13, 2024. It is now read-only.
/ pantam Public archive

The microframework for microservices

License

Notifications You must be signed in to change notification settings

flmnt/pantam

Repository files navigation

pantam

Peter the Pantam Python

Pantam is an extensible, ultra lightweight, Python framework for creating RESTful microservices.

Features include:

Need to build a Javascript microservice? Check out Bantam

Getting started

Our goal with Pantam is reduce the work bootstrapping microservices.

With Pantam you can create a basic REST API in 5 minutes or less.

Examples

Installation

We recommend using Poetry with Pyenv for dependency and environment management (this documentation will use Poetry throughout) but if you prefer pip or conda then crack on!

If you haven't done so already, setup your python environment and Poetry project:

% pyenv install 3.8.2
% pyenv local 3.8.2
% poetry init

NB: if you specify pantam as a package during the setup process, run poetry install and skip the next step.

Now install the Pantam package:

% poetry add pantam

Once you have installed Pantam you can initialise your app.

% poetry shell
% pantam init

Follow the CLI instructions and then start building your microservice!

Setup

Pantam expects the following folder structure:

| main.py       // can have any name, it's where you run your app
| actions        // where your domain logic sits
|  |  index.py   // primary logic lives here (might be all you need)
|  |  other.py   // add as many other "domains" as you like (optional)

In the root level main.py file add the following to run Pantam:

from pantam import Pantam

pantam = Pantam()

app = pantam.build()

if __name__ == "__main__":
    pantam.run("main", "app")

In the actions folder create the following files.

actions/index.py

class Index:
  def fetch_all(self):
    pass

  def fetch_single(self, request):
    pass

  def create(self, request):
    pass

  def update(self, request):
    pass

  def delete(self, request):
    pass

actions/other.py

class Other:
  def fetch_single(self, request):
    pass

  def create(self, request):
    pass

The setup above will make the following routes available:

GET      /            // Index.fetch_all()
GET      /{id}         // Index.fetch_single()
POST     /            // Index.create()
PATCH    /{id}         // Index.update()
DELETE   /{id}         // Index.delete()

GET      /other/{id}   // Other.fetch_single()
POST     /other       // Other.create()

And that's you ready to go!

Development

Configure the application to live reload on a given port as follows:

from pantam import Pantam

pantam = Pantam(debug=True)

app = pantam.build()

Then serve the app:

% pantam serve --dev

Your application will be served on http://localhost:5000

NB: Pantam looks for a PANTAM_ENV environment variable when serving the application and defaults to development if no variable is set.

Production

To serve your microservice in production use:

% pantam serve

Your application is served at http://your-host:5000

You can change the port number via the configuration options.

NB: in production you should set a PANTAM_ENV=production environment variable.

.pantamrc.json

After running pantam init you will have a .pantamrc.json file in your directory with some CLI config options like this:

{
  "actions_folder": "actions",
  "entrypoint": "example.py",
  "port": 5000,
  "dev_port": 5000
}

The .pantamrc.json file provides configuration options for the CLI. You only need to change it if you change your main file (entrypoint) or rename your actions folder.

Add New Routes

To add a new action (resource) you can either create a new file in the actions folder or use the CLI to make the file for you:

% pantam action index.py

You can add the standard methods (fetch_all, fetch_single, create, update, delete) to an action class which will automatically create the standard routes.

If you'd like to create custom methods for your action class you can create custom getters like this:

// GET -> /custom-method/
def get_custom_method(self):
  # your code here

And custom setters like this:

// POST -> /custom-method/
def set_custom_method(self, request):
  print(request)
  # your code here

From version 0.1.0 onwards you can also create a do method, which is a custom post method that also expects an identifier as part of the url.

// POST -> /custom-method/{id}
def do_custom_method(self, request):
  print(request)
  # your code here

Pantam will ignore methods that are not "standard" methods or do not start with get or set. However if you want to ensure that your method will be ignored you can prefix the method with a double underscore, like this:

def __my_hidden_method(self):
  // do something secret

Creating Responses

To create a response, make use of the Starlette response API, you can import all responses from starlette or import common responses from Pantam directly, including: JSONResponse, HTMLResponse, PlainTextResponse, FileResponse, RedirectResponse.

Here are a few examples:

from pantam import PlainTextResponse

class YourClass:
  def fetch_all():
    return PlainTextResponse("This is fetch all!")
from pantam import JSONResponse

class YourClass:
  def fetch_all():
    return JSONResponse([{ "content": "example" }])

Changing status code is also simple.

def fetch_all(self):
  return PlainTextResponse("This is fetch all!", status_code=404)

Adjusting headers can also be achieved.

def fetch_all(self):
  headers = {
    "Cache-Control": "no-cache"
  }
  return PlainTextResponse("This is fetch all!", headers=headers)

Configuration Options

For advanced configuration pass options in when instantiating Pantam.

from pantam import Pantam

pantam = Pantam(debug=True) # add options as below

app = pantam.build()

if __name__ == "__main__":
    pantam.run("main", "app")

You can set the following options:

debug: bool

Turns debugging mode on for Pantam (and underlying Starlette). Provides more verbose error messages. Should be off in production.

Default: False

actions_folder: string

The folder that contains your action files.

Default: "actions"


actions_index: string

The primary action file in your action folder.

Default: "index"


on_shutdown: function

Function called prior to shutdown.

Default: None

Debugging

If you're struggling to debug and issue and unsure what routes Pantam has created for you, set the debug option to True.

from pantam import Pantam

pantam = Pantam(debug=True)

app = pantam.build()

Also check trailing slashes in your urls, these are important.

In the example below the url test/1 and test/custom-method both trigger fetch_single() but the url test/custom-method/ (with the trailing slash) triggers get_custom_method().

// actions/test.py

// GET -> test/custom-method
// GET -> test/{id}
fetch_single()

// GET -> test/custom-method/
get_custom_method()

Contribution

We welcome feedback, suggestions and contributions.

If you have an idea you want to discuss please open an issue.

Licenses

Free for personal and commerical use under the MIT License