Skip to content

amigus/python3-demo-api

Repository files navigation

Python 3 Demo API

Python 3 Demo API is a JSON/REST API written in Python using the Flask web application framework with Marshmallow for JSON marshaling and SQLAlchemy with Alembic for database access and management. The API was tested with MariaDB and SQLite.

Login

The API has a minimal OAuth2/ OpenID Connect implementation based on Flask-JWT-Extended. It does email verification using AWS SES and the email must be verified before the user can authentication to get an access_token. Phone numbers are optional when adding a user and they are validated using the phonenumbers Python Library but they are not verified. In addition to getting a token and verifying an email, callers can reset passwords and get user information about themselves and other public users.

Functionality

The API itself has REST methods to get, set and list "thingy" types.

Development and testing environments

Install Python 3.7 and pip before you start.

The API uses Pipenv so setting up a (venv-based) environment is quick and easy:

  1. Install or upgrade Pipenv

    pip install --user --upgrade pipenv
  2. Clone the repo and setup the virtual environment:

    git clone git@github.com:amigus/python3-demo-app.git
    cd python3-demo-app
    pipenv install -d
  3. Create an instance folder, settings.py, test_settings.py:

    Linux/UN*X shell:

    mkdir -p instance
    cd instance
    cat <<EOF>>settings.py
    import os
    
    base_dir = os.path.dirname(os.path.abspath(__file__))
    
    SECRET_KEY = "arandomsecret"
    CLIENT_ID = "arandomstring"
    
    RATELIMIT_ENABLED = False
    
    SQLALCHEMY_DATABASE_URI = os.environ.get(
        "SQLALCHEMY_DATABASE_URI", f"sqlite:///{os.path.sep.join([base_dir, 'db.sqlite3'])}"
    )
    
    # DEBUG and testing features
    # SQLAlchemy will log all of the queries it execute
    SQLALCHEMY_ECHO = True
    # Flask will propagate exceptions; extensions test and use the setting too
    TESTING = True
    EOF
    cat <<EOF>>test_settings.py
    SECRET_KEY = "arandomsecret"
    CLIENT_ID = "arandomstring"
    RATELIMIT_ENABLED = False
    SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
    TESTING = True
    EOF
    cd ..

    Windows Powershell:

    mkdir "instance"
    cd "instance"
    New-Item "settings.py" -Value @"
    import os
    
    base_dir = os.path.dirname(os.path.abspath(__file__))
    
    SECRET_KEY = "arandomsecret"
    CLIENT_ID = "arandomstring"
    
    RATELIMIT_ENABLED = False
    
    SQLALCHEMY_DATABASE_URI = os.environ.get(
        "SQLALCHEMY_DATABASE_URI", f"sqlite:///{os.path.sep.join([base_dir, 'db.sqlite3'])}"
    )
    
    # DEBUG and testing features
    # SQLAlchemy will log all of the queries it execute
    SQLALCHEMY_ECHO = True
    # Flask will propagate exceptions; extensions test and use the setting too
    TESTING = True
    "@
    
    New-Item "test_settings.py" -Value @"
    SECRET_KEY = "arandomsecret"
    CLIENT_ID = "arandomstring"
    RATELIMIT_ENABLED = False
    SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
    TESTING = True
    "@
    cd ..
  4. Create a logging.yml (required when app.testing != True):

    Add LOGGING_YAML to settings.py:

    LOGGING_YAML = os.path.sep.join([base_dir, "logging.yml"])

    Create instance/logging.yml:

    Linux/UN*X shell:

    cat <<EOF>>instance/logging.yml
    version: 1
    formatters:
        detailed:
            format: "[%(asctime)s] [%(process)d] [%(levelname)s] [%(filename)s:%(lineno)d] [%(funcName)s] %(message)s"
    handlers:
        stdout:
            class: logging.StreamHandler
            formatter: detailed
            stream: ext://sys.stdout
    root:
        handlers: [stdout]
        level: INFO
    loggers:
        app:
            level: DEBUG
        db:
            level: DEBUG
        emailer:
            level: DEBUG
    EOF

    Windows Powershell:

    New-Item .\instance\logging.yml -Value @"
    version: 1
    formatters:
        detailed:
            format: "[%(asctime)s] [%(process)d] [%(levelname)s] [%(filename)s:%(lineno)d] [%(funcName)s] %(message)s"
    handlers:
        stdout:
            class: logging.StreamHandler
            formatter: detailed
            stream: ext://sys.stdout
    root:
        handlers: [stdout]
        level: INFO
    loggers:
        app:
            level: DEBUG
        db:
            level: DEBUG
        emailer:
            level: DEBUG
    "@
  5. Start the pipenv shell:

    pipenv shell
  6. Create the SQLite development database:

    flask db upgrade

    NOTE: the database will now exist as db.sqlite3 in the instance folder.

  7. Run the server:

    flask run --no-reload

Note when pulling

If the changes include changes to the Alembic migrations, be sure to run flask db upgrade within the virtual environment.

If the changes include changes to the Pipfile or Pipfile.lock, be sure to run pipenv sync.

About

A Demo API written in Python 3

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published