Metadata-Version: 2.1
Name: pantam
Version: 0.0.1a1
Summary: The microframework for microservices
License: MIT
Author: Matt Davies
Author-email: matt@filament.so
Requires-Python: >=3.6,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Requires-Dist: PyInquirer (>=1.0.3,<2.0.0)
Requires-Dist: colored (>=1.4.2,<2.0.0)
Requires-Dist: shellingham (>=1.3.2,<2.0.0)
Requires-Dist: starlette (>=0.13.6,<0.14.0)
Requires-Dist: typer (>=0.3.1,<0.4.0)
Requires-Dist: uvicorn (>=0.11.6,<0.12.0)
Description-Content-Type: text/markdown

# pantam

<img src="https://raw.githubusercontent.com/flmnt/pantam/master/logo/logo.png" alt="Peter the Pantam Python" width="300">

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

Features include:

- built on top of [Starlette](https://www.starlette.io/)
- simple REST routing
- [segregated business logic](https://en.wikipedia.org/wiki/Separation_of_concerns)
- [convention over configuration](https://en.wikipedia.org/wiki/Convention_over_configuration) paradigm
- expressive logging (decent error reporting!)
- live reloading in developer mode

Need to build a Javascript microservice? [Check out Bantam](https://github.com/flmnt/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

- [Domain segregated example](https://github.com/flmnt/pantam/tree/master/example/domain)
- [Event based example](https://github.com/flmnt/pantam/tree/master/example/event)

### Installation

We recommend using [Poetry](https://python-poetry.org/) 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:

```
| index.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 `index.py` file add the following to run Pantam:

```
from pantam import Pantam

pantam = Pantam()

app = pantam.build()
```

In the `actions` folder create the following files.

`actions/index.py`

```
class Index:
  def fetch_all(self):
    pass

  def fetch_single(self, uid):
    pass

  def create(self, data):
    pass

  def update(self, uid, data):
    pass

  def delete(self, uid):
    pass
```

`actions/other.py`

```
class Other:
  def fetch_single(self, uid):
    pass

  def create(self, data):
    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

Start the development server with:

```
% pantam serve --dev
```

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

In development mode, when you make changes to files the application will update itself.

### 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.

## .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"
  "dev_port": 5000
  "port": 5000
}
```

The `.pantamrc.json` file provides configuration options for the CLI. You only need to change it if you want to serve the application on different ports, 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, data):
  print(data)
  # 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](https://www.starlette.io/responses/), 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)
```

## 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](https://github.com/flmnt/pantam/issues/new).

## Licenses

Free for personal and commerical use under the [MIT License](https://github.com/flmnt/pantam/blob/master/LICENSE.md)

