An effective, simple, and async security library for the Sanic framework.

Overview

Downloads Code style: black Conda Conda Downloads


Sanic Security

An effective, simple, and async security library for the Sanic framework.

Table of Contents

About The Project

Sanic Security is an authentication, authorization, and verification library designed for use with Sanic. This library contains a variety of features including:

  • Login, registration, and authentication (including access/refresh tokens)
  • Two-factor authentication
  • Two-step verification
  • Captcha
  • Role based authorization with wildcard permissions

This repository has been starred by Sanic's core maintainer:

aphopkins

Please visit security.sunsetdeveloper.com for documentation.

Getting Started

In order to get started, please install pip.

Prerequisites

  • pip
sudo apt-get install python3-pip

Installation

  • Install the Sanic Security pip package.
pip3 install sanic-security
  • Fork Sanic Security and install development dependencies.
pip3 install -e ".[dev]"

Configuration

Sanic Security configuration is merely an object that can be modified either using dot-notation or like a dictionary.

For example:

from sanic_security.configuration import config

config.SECRET = "This is a big secret. Shhhhh"
config["CAPTCHA_FONT"] = "./resources/captcha.ttf"

You can also use the update() method like on regular dictionaries.

Any environment variables defined with the SANIC_SECURITY_ prefix will be applied to the config. For example, setting SANIC_SECURITY_SECRET will be loaded by the application automatically and fed into the SECRET config variable.

You can load environment variables with a different prefix via calling the config.load_environment_variables("NEW_PREFIX_") method.

  • Default configuration values:
Key Value Description
SECRET This is a big secret. Shhhhh The secret used by the hashing algorithm for generating and signing JWTs. This should be a string unique to your application. Keep it safe.
CACHE ./security-cache The path used for caching.
SESSION_SAMESITE strict The SameSite attribute of session cookies.
SESSION_SECURE False The Secure attribute of session cookies.
SESSION_HTTPONLY True The HttpOnly attribute of session cookies. HIGHLY recommended that you do not turn this off, unless you know what you are doing.
SESSION_DOMAIN None The Domain attribute of session cookies.
SESSION_EXPIRES_ON_CLIENT False When true, session cookies are removed from the clients browser when the session expires.
SESSION_ENCODING_ALGORITHM HS256 The algorithm used to encode sessions to a JWT.
SESSION_PREFIX token Prefix attached to the beginning of session cookies.
MAX_CHALLENGE_ATTEMPTS 5 The maximum amount of session challenge attempts allowed.
CAPTCHA_SESSION_EXPIRATION 60 The amount of seconds till captcha session expiration on creation. Setting to 0 will disable expiration.
CAPTCHA_FONT captcha.ttf The file path to the font being used for captcha generation.
TWO_STEP_SESSION_EXPIRATION 200 The amount of seconds till two step session expiration on creation. Setting to 0 will disable expiration.
AUTHENTICATION_SESSION_EXPIRATION 2692000 The amount of seconds till authentication session expiration on creation. Setting to 0 will disable expiration.
ALLOW_LOGIN_WITH_USERNAME False Allows login via username and email.
TEST_DATABASE_URL sqlite://:memory: Database URL for connecting to the database Sanic Security will use for testing.

Usage

Sanic Security's authentication and verification functionality is session based.

A new session will be created for the user after the user logs in or requests some form of verification (two-step, captcha). The session data is then encoded into a JWT and stored on a cookie on the user’s browser. The session cookie would be sent along with every subsequent request. The server can then compare the session stored on the cookie against the session information stored in the database to verify user’s identity and send a response with the corresponding state.

The tables in the below examples represent example request form-data (https://sanicframework.org/en/guide/basics/request.html#form).

Authentication

  • Registration

Phone can be null or empty.

Key Value
username example
email [email protected]
phone 19811354186
password testpass
captcha Aj8HgD
@app.post("api/auth/register")
@requires_captcha()
async def on_register(request, captcha_session):
    account = await register(request)
    two_step_session = await request_two_step_verification(request, account)
    await email_code(
        two_step_session.code
    )  # Custom method for emailing verification code.
    response = json("Registration successful!", two_step_session.bearer.json())
    two_step_session.encode(response)
    return response
  • Verify Account
Key Value
code G8ha9nVae
@app.post("api/auth/verify")
async def on_verify(request):
    two_step_session = await verify_account(request)
    return json(
        "You have verified your account and may login!", two_step_session.bearer.json()
    )
  • Login

Login credentials are retrieved via the Authorization header. Credentials are constructed by first combining the username and the password with a colon (aladdin:opensesame), and then by encoding the resulting string in base64 (YWxhZGRpbjpvcGVuc2VzYW1l). Here is an example authorization header: Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l.

You can use a username as well as an email for login if ALLOW_LOGIN_WITH_USERNAME is true in the config.

@app.post("api/auth/login")
async def on_login(request):
    authentication_session = await login(request)
    response = json("Login successful!", authentication_session.bearer.json())
    authentication_session.encode(response)
    return response
  • Login (With two-factor authentication)
@app.post("api/auth/login")
async def on_two_factor_login(request):
    authentication_session = await login(request, two_factor=True)
    two_step_session = await request_two_step_verification(
        request, authentication_session.bearer
    )
    await email_code(
        two_step_session.code
    )  # Custom method for emailing verification code.
    response = json(
        "Login successful! A second factor is now required to be authenticated.",
        authentication_session.bearer.json(),
    )
    authentication_session.encode(response)
    two_step_session.encode(response)
    return response
  • Second Factor
Key Value
code G8ha9nVae
@app.post("api/auth/login/second-factor")
@requires_two_step_verification()
async def on_login_second_factor(request, two_step_session):
    authentication_session = await on_second_factor(request)
    response = json(
        "Second factor attempt successful! You may now be authenticated!",
        authentication_session.bearer.json(),
    )
    return response
  • Logout
@app.post("api/auth/logout")
@requires_authentication()
async def on_logout(request, authentication_session):
    await logout(authentication_session)
    response = json("Logout successful!", authentication_session.bearer.json())
    return response
  • Refresh Authentication

A refresh token is used that lets the client retrieve a new authentication session without having to ask the user to log in again.

@app.post("api/auth/refresh")
async def on_refresh(request):
    refreshed_authentication_session = await refresh_authentication(request)
    response = json(
        "Authentication session refreshed!",
        refreshed_authentication_session.bearer.json(),
    )
    refreshed_authentication_session.encode(response)
    return response
  • Requires Authentication
@app.post("api/auth")
@requires_authentication()
async def on_authenticated(request, authentication_session):
    return json(
        f"Hello {authentication_session.bearer.username}! You have been authenticated.",
        authentication_session.bearer.json(),
    )

Captcha

You must download a .ttf font for captcha challenges and define the file's path in the configuration.

1001 Free Fonts

Recommended Font

Captcha challenge example:

Captcha image.

  • Request Captcha
@app.get("api/captcha")
async def on_request_captcha(request):
    captcha_session = await request_captcha(request)
    response = await captcha_session.get_image()
    captcha_session.encode(response)
    return response
  • Requires Captcha
Key Value
captcha Aj8HgD
@app.post("api/captcha")
@requires_captcha()
async def on_captcha_attempt(request, captcha_session):
    return json("Captcha attempt successful!", captcha_session.json())

Two-step Verification

  • Request Two-step Verification
Key Value
email [email protected]
captcha Aj8HgD
@app.post("api/verification/request")
@requires_captcha()
async def on_request_verification(request, captcha_session):
    two_step_session = await request_two_step_verification(request)
    await email_code(
        two_step_session.code
    )  # Custom method for emailing verification code.
    response = json("Verification request successful!", two_step_session.bearer.json())
    two_step_session.encode(response)
    return response
  • Resend Two-step Verification Code
@app.post("api/verification/resend")
async def on_resend_verification(request):
    two_step_session = await TwoStepSession.decode(request)
    await email_code(
        two_step_session.code
    )  # Custom method for emailing verification code.
    return json("Verification code resend successful!", two_step_session.bearer.json())
  • Requires Two-step Verification
Key Value
code G8ha9nVa
@app.post("api/verification")
@requires_two_step_verification()
async def on_verification(request, two_step_session):
    response = json(
        "Two-step verification attempt successful!", two_step_session.bearer.json()
    )
    return response

Authorization

Sanic Security uses role based authorization with wildcard permissions.

Roles are created for various job functions. The permissions to perform certain operations are assigned to specific roles. Users are assigned particular roles, and through those role assignments acquire the permissions needed to perform particular system functions. Since users are not assigned permissions directly, but only acquire them through their role (or roles), management of individual user rights becomes a matter of simply assigning appropriate roles to the user's account; this simplifies common operations, such as adding a user, or changing a user's department.

Wildcard permissions support the concept of multiple levels or parts. For example, you could grant a user the permission printer:query, printer:query,delete, and/or printer:*.

  • Assign Role
await assign_role(
    "Chat Room Moderator",
    "Can read and delete messages in all chat rooms, suspend and mute accounts, and control voice chat.",
    "channels:view,delete, account:suspend,mute, voice:*",
    bearer,
)
  • Require Permissions
@app.post("api/channel/view")
@require_permissions("channels:view", "voice:*")
async def on_voice_chat_control(request, authentication_session):
    return text("Voice chat is now being controlled.")
  • Require Roles
@app.post("api/account/suspend")
@require_roles("Chat Room Moderator")
async def on_suspend_account(request, authentication_session):
    return text("Account successfully suspended.")

Testing

  • Set the TEST_DATABASE_URL configuration value.

  • Make sure the test Sanic instance (test/server.py) is running on your machine.

  • Run the unit test client (test/tests.py) and wait for results.

Tortoise

Sanic Security uses Tortoise ORM for database operations.

Tortoise ORM is an easy-to-use asyncio ORM (Object Relational Mapper).

  • Initialise your models and database like so:
async def init():
    await Tortoise.init(
        db_url="sqlite://db.sqlite3",
        modules={"models": ["sanic_security.models", "app.models"]},
    )
    await Tortoise.generate_schemas()

or

register_tortoise(
    app,
    db_url="sqlite://db.sqlite3",
    modules={"models": ["sanic_security.models", "app.models"]},
    generate_schemas=True,
)
  • Define your models like so:
from tortoise.models import Model
from tortoise import fields


class Tournament(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()
  • Use it like so:
# Create instance by save
tournament = Tournament(name="New Tournament")
await tournament.save()

# Or by .create()
await Tournament.create(name="Another Tournament")

# Now search for a record
tour = await Tournament.filter(name__contains="Another").first()
print(tour.name)

Support for SQLAlchemy coming soon.

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the GNU General Public License v3.0. See LICENSE for more information.

Versioning

0.0.0

  • MAJOR version when you make incompatible API changes.

  • MINOR version when you add functionality in a backwards compatible manner.

  • PATCH version when you make backwards compatible bug fixes.

https://semver.org/

Comments
  • Add MANIFEST.in file

    Add MANIFEST.in file

    This is in accordance to https://packaging.python.org/gu…ides/using-manifest-in/

    I'm trying to add this package to conda-forge and right now the package isn't picking up the requirement.txt file, this should help!

    opened by thewchan 9
  • I made a thing

    I made a thing

    First, great work.

    Second, this has some stuff in it:

    • Moved to pytest for testing (including support for iterating through ORMs)
    • Moved to sanic-testing for the testing of Sanic to be uniform and supportable
    • Moved to poetry for package and dependency management
    • Bumped the version to 2.0.0_preview_01 just because
    • Made the tortoise-orm stuff a little more normalized (read: less Tortoise-ish, more whatever)
    • Built and bundled in a umongo option (what I use)
    • Support for bring your own ORM (need to document this, but basically you pass in, via config variables, your Models/Objects which must have a few items)
    • Updated all the needed modules to current versions
    • Force username, as well as phone and email to be unique, since all can be used to login
    • Force role names to be unique, because that's sanity
    • Moved model validators into their respective ORM, using their respective best practices
    • Started to make the module pluge-able to Sanic, via sanic-ext ... but recent updates broke what was working, and the developers said they are working on overhauling it, so I left it as is for now
    • Added some more variables:
        "SANIC_SECURITY_ORM": 'tortoise', # Currently supports ['tortoise', 'umongo']
        "SANIC_SECURITY_ACCOUNT": None,
        "SANIC_SECURITY_SESSION": None,
        "SANIC_SECURITY_ROLE": None,
        "SANIC_SECURITY_VERIFICATION_MODEL": None,
        "SANIC_SECURITY_TWOSTEP_MODEL": None,
        "SANIC_SECURITY_CAPTCHA_MODEL": None,
        "SANIC_SECURITY_AUTHENTICATION_MODEL": None,
    

    Third, I suck at documentation (including docstrings), and lots is needed, so I'll start working on that next. I tried to maintain as much backwards support as possible .. but some things just needed to change (hence the major version bump) to be sane and relatively clean.

    Lastly, the umongo.py ORM file still needs some cleanup -- nothing breaking, just code quality and DRYness.

    opened by pahrohfit 5
  • sanic response cookie seems need type str rather than byte

    sanic response cookie seems need type str rather than byte

    Describe the bug sanic response cookie seems need type str rather than bytes, or got TypeError

    // tested with sanic 20.12.3, 21.6.2

    To Reproduce server use test/server.py client use curl:

    //1. reg user //ok

    curl -sv http://127.0.0.1:8000/api/test/auth/register [email protected] \
     -Fusername=test -Fpassword=testtest -Fverified=true
    

    //2. login user // fail TypeError // should login success

    curl -sv http://127.0.0.1:8000/api/test/auth/login --user '[email protected]:testtest' -d ''
    
    [2022-01-22 09:34:03 +0800] [1732395] [ERROR] Exception occurred while handling uri: 'http://127.0.0.1:8000/api/test/auth/login'
    Traceback (most recent call last):
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/server.py", line 509, in write_response
        response.output(
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/response.py", line 169, in output
        return self.get_headers(version, keep_alive, keep_alive_timeout, body)
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/response.py", line 64, in get_headers
        return format_http1_response(self.status, self.headers.items(), body)
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/headers.py", line 194, in format_http1_response
        headerbytes = format_http1(headers)
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/headers.py", line 184, in format_http1
        return "".join(f"{name}: {val}\r\n" for name, val in headers).encode()
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/headers.py", line 184, in <genexpr>
        return "".join(f"{name}: {val}\r\n" for name, val in headers).encode()
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/cookies.py", line 137, in __str__
        output = ["%s=%s" % (self.key, _quote(self.value))]
      File "/home/chen/.local/lib/python3.8/site-packages/sanic/cookies.py", line 30, in _quote
        if str is None or _is_legal_key(str):
    TypeError: cannot use a string pattern on a bytes-like object
    

    Version // sanic-security 1.4.7

    • sanic 20.12.3 + py3.8
    • sanic 21.6.2 + py3.9

    Workaround seems in sanic 20.12.3, 21.6.2 response.cookie should be str type.

    https://github.com/sunset-developer/sanic-security/blob/v1.4.7/sanic_security/models.py#L288

    changes:

            response.cookies[cookie] = jwt.encode(
                payload, security_config.SECRET, security_config.SESSION_ENCODING_ALGORITHM
    -        )
    +        ).decode('utf-8')
    
    opened by yurenchen000 2
  • Reformating

    Reformating

    Unfortunately, I was not able to test whether my changes are breaking or not. I have reviewed them multiple times, and I expect that they would not be breaking.

    I tried to not change any of the behavior because it was described as stable.

    opened by HelixAchaos 2
  • Documentation and DRYness

    Documentation and DRYness

    • Finished README.md file (I think)
    • Moved .decode() property to the utils module, as I was able to decouple it from the ORM, thus making it more DRY and better suited for BYO-ORM
    • Added a .lookup() classmethod to all of the Session classes.
    opened by pahrohfit 0
  • Documentation and DRYness

    Documentation and DRYness

    • Finished README.md file (I think)
    • Moved .decode() property to the utils module, as I was able to decouple it from the ORM, thus making it more DRY and better suited for BYO-ORM
    • Added a .lookup() classmethod to all of the Session classes.
    opened by pahrohfit 0
  • Showcase Feedback

    Showcase Feedback

    => you have a license mismatch (https://github.com/sunset-developer/sanic-security/blob/main/setup.py#L15)

    => you default to HTTP cookies that do not have secure flag set (https://github.com/sunset-developer/sanic-security/blob/main/sanic_security/configuration.py#L29)

    => your project requires phone number, and the regex doesnt support any non US format (https://github.com/sunset-developer/sanic-security/blob/main/sanic_security/authentication.py#L74)

    => your project does not check for common passwords such as "password", "qwerty", etc

    opened by sunset-developer 0
  • ORM objects into regular objects in models.py

    ORM objects into regular objects in models.py

    In order to rip out Tortoise, we need to convert the current ORM objects into regular objects in models.py.

    I began the process by converting the BaseModel and Account objects.

    This commit provides a demonstration as to what was changed and what was removed.

    https://github.com/sunset-developer/sanic-security/commit/7a0cb6443142d9d2287ac5b9187cf7420a7efea2

    Simply, any line of code that uses Tortoise must be removed or changed in a way that can have a similar function but without requiring retrieving the object from the database, for example: requiring a parameter in a method so the object has to be passed in.

    opened by sunset-developer 0
Releases(v1.9.7)
  • v1.9.7(Dec 5, 2022)

  • v1.9.6(Dec 2, 2022)

  • v1.9.5(Dec 2, 2022)

    • Account associated to new two-step session on two-step verification request can now be retrieved from an existing two-step session.
    • Unit test client additions.
    • Documentation revision.
    Source code(tar.gz)
    Source code(zip)
  • v1.9.4(Nov 29, 2022)

  • v1.9.3(Nov 17, 2022)

  • v1.9.2(Nov 17, 2022)

  • v1.9.1(Nov 16, 2022)

  • v1.9.0(Sep 28, 2022)

    • Usernames are now required to be unique.
    • Captcha and verification modules merged.
    • Session deactivate() method implemented.
    • Test client/server revisions.
    • README.md and documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.8.3(Jun 7, 2022)

    • SESSION_SECURE config field default is now set to True.
    • Phone number format check revision.
    • token field removed from Session. Sessions are now retrieved via id when decoding.
    • setup.py license mismatch revision.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.8.2(May 29, 2022)

  • v1.8.1(May 23, 2022)

  • v1.8.0(May 23, 2022)

  • v1.7.1(May 21, 2022)

    • Refresh authentication improvements.
    • Methods decode_to_refresh() and validate_refresh() implemented in AuthenticationSession
    • refresh_authentication() method revised.
    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(May 20, 2022)

    • On-the-fly verification code and captcha image generation.
    • SessionFactory removed and replaced with new() class method.
    • redeem() method removed and code moved to refresh_authentication() method.
    • refresh_expiration_date field added to AuthenticationSession.
    • Util methods get_code() and get_expiration_date() implemented.
    • CaptchaSession method get_image() returns raw() instead of file() and is no longer async.
    • assign_role() method parameters permissions and description are optional.
    • Test server and client revisions.
    • logout() method will raise error if session is already deactivated.
    • Unrecognized location check removed.
    • CACHE configuration field removed.
    • Licensing revision.
    • Log message revisions.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(May 6, 2022)

  • v1.5.0(Apr 28, 2022)

    • Improved type hinting on model variables and methods.
    • Improved two-step session code generation. It is recommended to clear your cache due to these changes.
    • generate_initial_admin renamed to create_initial_admin_account.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.11(Mar 17, 2022)

  • v1.4.10(Feb 15, 2022)

  • v1.4.9(Feb 5, 2022)

  • v1.4.8(Jan 24, 2022)

  • v1.4.7(Jan 21, 2022)

    • Authorization fix that takes roles marked as deleted into consideration.
    • Account retrieval methods filter out accounts marked as deleted instead of relying on validation.
    • Improved model type hinting.
    • Minor testing adjustments and fixes.
    • Licensing revision.
    • License statement attached to source files.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.6(Jan 19, 2022)

  • v1.4.5(Jan 18, 2022)

    • Refresh token and redeem method are no longer inherited from Session and resides in AuthenticationSession.
    • Captcha and two-step session request improvements.
    • Invalid credentials for registration now raise CredentialsError.
    • Session context (ctx) field for storing extra information.
    • MaxedOutChallangeError exception implemented and raised when a session's challenge attempts has reached it's threshold.
    • Error message clarification.
    • Improved error handling.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.4(Jan 13, 2022)

    • Previous client session is deactivated when a new one is requested (for example when requesting captcha).
    • Two-factor authentication fix and error message clarification.
    • Documentation revision.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.3(Jan 7, 2022)

    • Login credentials are received via authorization header.
    • Tests revised accordingly to use authorization header.
    • Major documentation revisions.
    • MAX_ATTEMPTS_ALLOWED configuration field added.
    • CredentialsError exception implemented for an invalid login.
    • JWTDecodeError exception implemented if an error occurs during session JWT decoding.
    • ChallengeError exception implemented if a verification session challenge attempt is incorrect.
    • crosscheck_code method renamed to check_code
    Source code(tar.gz)
    Source code(zip)
  • v1.4.2(Jan 6, 2022)

    • validate_location renamed to check_client_location.
    • UnrecognisedLocationError now raised instead of SessionError when checking client location.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.1(Jan 3, 2022)

    • Improved refresh token reuse protection.
    • crosscheck_location renamed to validate_location.
    • Sessions marked as deleted won't be taken into consideration during location validation.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Jan 2, 2022)

    • Authorization revamp. Permission object removed as permissions are stored in a Role object. An account's roles can be accessed via the roles variable value via a many-to-many relationship.
    • Session access/refresh token's.
    • Model revisions.
    • Improved registration error handling.
    • Password character limit check during registration.
    • Uid removed.
    • Test improvements.
    • Documentation revisions.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.3(Dec 29, 2021)

  • v1.3.2(Dec 19, 2021)

Owner
Sunset Dev
May the bridges you burn light your way.
Sunset Dev
A framework that let's you compose websites in Python with ease!

Perry Perry = A framework that let's you compose websites in Python with ease! Perry works similar to Qt and Flutter, allowing you to create componen

Linkus 13 Oct 09, 2022
A python application to log QSOs directly to QRZ.com from the command line

qrzlogger This script is a QRZ.com command line QSO logger. It does the following: asks the user for a call sign displays available call sign info pul

Michael Clemens 15 Jul 16, 2021
A simple todo app using flask and sqlachemy

TODO app This is a simple TODO app made using Flask. Packages used: DoodleCSS Special thanks to Chris McCormick (@mccrmx) :) Flask Flask-SQLAlchemy Fl

Lenin 1 Dec 26, 2021
TinyAPI - 🔹 A fast & easy and lightweight WSGI Framework for Python

TinyAPI - 🔹 A fast & easy and lightweight WSGI Framework for Python

xArty 3 Apr 08, 2022
You can use the mvc pattern in your flask application using this extension.

You can use the mvc pattern in your flask application using this extension. Installation Run the follow command to install mvc_flask: $ pip install mv

Marcus Pereira 37 Dec 17, 2022
Screaming-fast Python 3.5+ HTTP toolkit integrated with pipelining HTTP server based on uvloop and picohttpparser.

Japronto! There is no new project development happening at the moment, but it's not abandoned either. Pull requests and new maintainers are welcome. I

Paweł Piotr Przeradowski 8.6k Dec 29, 2022
Try to create a python mircoservice framework.

Micro current_status: prototype. ... Python microservice framework. More in Document. You should clone this project and run inv docs. Install Not now.

修昊 1 Dec 07, 2021
web.py is a web framework for python that is as simple as it is powerful.

web.py is a web framework for Python that is as simple as it is powerful. Visit http://webpy.org/ for more information. The latest stable release 0.62

5.8k Dec 30, 2022
A Simple Kivy Greeting App

SimpleGreetingApp A Simple Kivy Greeting App This is a very simple GUI App that receives a name text input from the user and returns a "Hello" greetin

Mariya 40 Dec 02, 2022
An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API.

django-rest-client An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API. Suitable for APIs made wit

Certego 4 Aug 25, 2022
Distribution Analyser is a Web App that allows you to interactively explore continuous distributions from SciPy and fit distribution(s) to your data.

Distribution Analyser Distribution Analyser is a Web App that allows you to interactively explore continuous distributions from SciPy and fit distribu

Robert Dzudzar 46 Nov 08, 2022
Phoenix LiveView but for Django

Reactor, a LiveView library for Django Reactor enables you to do something similar to Phoenix framework LiveView using Django Channels. What's in the

Eddy Ernesto del Valle Pino 526 Jan 02, 2023
A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs.

cx_Oracle_async A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs. Easy to use , buy may not

36 Dec 21, 2022
Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints.

Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints. check parameters and generate API documents automatically. Flask Sugar是一个基于flask,pyddantic,类型注解的API框架

162 Dec 26, 2022
A PC remote controller for YouTube and Twitch

Lazynite Lazynite is a PC remote controller for YouTube and Twitch on Telegram. Features Volume control; Browser fullscreen / video fullscreen; PC shu

Alessio Celentano 46 Nov 12, 2022
FastAPI framework, high performance, easy to learn, fast to code, ready for production

FastAPI framework, high performance, easy to learn, fast to code, ready for production Documentation: https://fastapi.tiangolo.com Source Code: https:

Sebastián Ramírez 53k Jan 02, 2023
The Web framework for perfectionists with deadlines.

Django Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out. All docu

Django 67.9k Dec 29, 2022
Free and open source full-stack enterprise framework for agile development of secure database-driven web-based applications, written and programmable in Python.

Readme web2py is a free open source full-stack framework for rapid development of fast, scalable, secure and portable database-driven web-based applic

2k Dec 31, 2022
APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects

APIFlask APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects. It's easy to use, highly customizable, ORM/O

Grey Li 705 Jan 04, 2023
The comprehensive WSGI web application library.

Werkzeug werkzeug German noun: "tool". Etymology: werk ("work"), zeug ("stuff") Werkzeug is a comprehensive WSGI web application library. It began as

The Pallets Projects 6.2k Jan 01, 2023