Skip to main content

Artless and minimalistic web framework without dependencies, working over WSGI.

Project description

artless-framework

PyPI - License Development Status PyPI Version PyPI - Python Version Downloads

The artless and minimalistic web framework without dependencies, working over WSGI.

Main principles

  1. Artless, fast and small (less then 1000 LOC into a single module) WSGI-framework.
  2. No third party dependencies (standart library only).
  3. Support only modern versions of Python (>=3.10).
  4. Mostly pure functions without side effects.
  5. Interfaces with type annotations.
  6. Comprehensive documentation with examples of use.
  7. Full test coverage.

Limitations

  • No Async/ASGI support.
  • No built-in support for working with Cookies.
  • Requests with multipart/form-data content-type are not supported.
  • No built-in protections, such as: CSRF, XSS, clickjacking and other attack techniques.

Installation

$ pip install artless-framework

Usages

from http import HTTPStatus
from os import getenv
from string import Template

from artless import App, Request, Response, ResponseFactory

HTML_TEMPLATE = Template(
    """
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>Say hello</title>
      </head>
      <body>
        <h1>Hello, $username!</h1>
      </body>
    </html>
    """
)


def say_hello(request: Request, username: str) -> Response:
    available_formats = {
        "json": ResponseFactory.json({"hello": username}),
        "plain": ResponseFactory.plain(f"Hello, {username}!"),
        "html": ResponseFactory.html(HTML_TEMPLATE.substitute(username=username)),
    }

    format = request.query.get("format", ["plain"])[0]

    if format not in available_formats:
        return ResponseFactory.create(status=HTTPStatus.BAD_REQUEST)

    return available_formats[format]


def create_application() -> App:
    app = App()
    app.set_routes([("GET", r"^/hello/(?P<username>\w+)$", say_hello)])
    return app


application = create_application()

if __name__ == "__main__":
    from wsgiref.simple_server import make_server

    host = getenv("HOST", "127.0.0.1")
    port = int(getenv("PORT", 8000))

    with make_server(host, port, application) as httpd:
        print(f"Started WSGI server on {host}:{port}")
        httpd.serve_forever()

Run it:

$ python3 app.py
Started WSGI server on 127.0.0.1:8000

Check it:

$ curl http://127.0.0.1:8000/hello/Peter
Hello, Peter!

$ curl http://127.0.0.1:8000/hello/Peter?format=html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Say hello</title>
  </head>
  <body>
    <h1>Hello, Peter!</h1>
  </body>
</html>

$ curl http://127.0.0.1:8000/hello/Peter?format=json
{"hello": "Peter"}

See more examples.

Configureation

By default, the application defines the following config:

{
    "DEBUG": False,
    "TEMPLATES_DIR": "templates",
    "LOGGING": {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "default": {
                "format": "[{asctime}] [{process:d}] [{levelname}] {message}",
                "datefmt": "%Y-%m-%d %H:%M:%S",
                "style": "{",
            },
        },
        "handlers": {
            "stdout": {
                "formatter": "default",
                "level": "INFO",
                "class": "logging.StreamHandler",
                "stream": "ext://sys.stdout",
            }
        },
        "loggers": {
            "artless": {
                "level": "INFO",
                "handlers": ["stdout"],
                "propagate": False,
            }
        },
        "root": {"level": "WARNING", "handlers": ["stdout"]},
    },
}

Before creating an application instance, set the configuration by overriding existing values ​​and/or adding a new ones:

from artless import Config, App


Config().replace({"debug": True, "database": {"host": "localhost"}})
application = App()

To get values ​​from the config, anywhere in the application:

from artless import Config


db_host = Config().database.get("host")
...

Roadmap

  • Add ASGI support.
  • Add plugin support.
  • Add cookies support.
  • Add async interface.
  • Add multipart/form-data support.
  • Add test client.
  • Add benchmarks.
  • Add more examples.
  • Add Sphinx doc.

Project details


Download files

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

Source Distribution

artless_framework-0.1.4.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

artless_framework-0.1.4-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file artless_framework-0.1.4.tar.gz.

File metadata

  • Download URL: artless_framework-0.1.4.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for artless_framework-0.1.4.tar.gz
Algorithm Hash digest
SHA256 354148bd5e854989b366e7f4d1b9a17c99b2919f05107f82e57ac5cf6424b18d
MD5 96a14f9dd0c491f1605f2a8b1e93962a
BLAKE2b-256 09c6d8955b4dec69a3b8730e6859d83ec7dccde685c8aa639041c5ac2d82a97a

See more details on using hashes here.

File details

Details for the file artless_framework-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for artless_framework-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 2a2e20a932588a871eab2797f799c419cf3511f5eb9328e6434a06f0f4d2a27e
MD5 feb1dc9e044b62e8bc15b997824877a6
BLAKE2b-256 bc7452c99968a11b634c9ae6bd2d14f80a0c92e5e34f00284e9dac056853a268

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page