├── .python-version ├── .gitignore ├── .dockerignore ├── examples ├── .gitignore ├── sqlite │ ├── compose.yml │ └── superset_config.py ├── postgres │ ├── compose.yml │ └── superset_config.py ├── mysql │ ├── superset_config.py │ └── compose.yml ├── demo.sh ├── celery │ ├── compose.yml │ └── superset │ │ └── superset_config.py └── README.md ├── bin ├── superset-demo └── superset-init ├── .github └── workflows │ ├── latest.yml │ └── push.yml ├── Makefile ├── Pipfile ├── LICENSE ├── Dockerfile ├── README.md ├── requirements.txt └── requirements-dev.txt /.python-version: -------------------------------------------------------------------------------- 1 | 3.12.11 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.docker/ 2 | **/.env 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !bin/ 3 | !requirements*.txt 4 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | **/*.db 2 | **/__pycache__ 3 | -------------------------------------------------------------------------------- /bin/superset-demo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | # Initialize Superset 5 | superset-init 6 | 7 | # Load some data to play with 8 | superset load_examples 9 | -------------------------------------------------------------------------------- /bin/superset-init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | # Create an admin user 5 | flask fab create-admin $@ 6 | 7 | # Initialize the database 8 | superset db upgrade 9 | 10 | # Create default roles and permissions 11 | superset init 12 | -------------------------------------------------------------------------------- /examples/sqlite/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | redis: 3 | image: redis 4 | restart: always 5 | volumes: 6 | - redis:/data 7 | superset: 8 | image: amancevice/superset 9 | restart: always 10 | depends_on: 11 | - redis 12 | environment: 13 | MAPBOX_API_KEY: ${MAPBOX_API_KEY} 14 | SUPERSET_HOME: /etc/superset 15 | ports: 16 | - "8088:8088" 17 | volumes: 18 | - ./superset_config.py:/etc/superset/superset_config.py 19 | - superset:/var/lib/superset 20 | volumes: 21 | redis: 22 | superset: 23 | -------------------------------------------------------------------------------- /.github/workflows/latest.yml: -------------------------------------------------------------------------------- 1 | name: latest 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - multiarch 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v4 13 | - run: npm install -g dockerlint 14 | - run: dockerlint 15 | build: 16 | runs-on: ubuntu-latest 17 | needs: lint 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: docker/setup-qemu-action@v3 21 | - uses: docker/setup-buildx-action@v3 22 | - uses: docker/build-push-action@v6 23 | with: 24 | platforms: | 25 | linux/amd64 26 | -------------------------------------------------------------------------------- /examples/sqlite/superset_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | MAPBOX_API_KEY = os.getenv("MAPBOX_API_KEY", "") 4 | CACHE_CONFIG = { 5 | "CACHE_TYPE": "RedisCache", 6 | "CACHE_DEFAULT_TIMEOUT": 300, 7 | "CACHE_KEY_PREFIX": "superset_", 8 | "CACHE_REDIS_HOST": "redis", 9 | "CACHE_REDIS_PORT": 6379, 10 | "CACHE_REDIS_DB": 1, 11 | "CACHE_REDIS_URL": "redis://redis:6379/1", 12 | } 13 | FILTER_STATE_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_filter_"} 14 | EXPLORE_FORM_DATA_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_explore_form_"} 15 | SQLALCHEMY_DATABASE_URI = "sqlite:////var/lib/superset/superset.db" 16 | SQLALCHEMY_TRACK_MODIFICATIONS = True 17 | SECRET_KEY = "thisISaSECRET_1234" 18 | -------------------------------------------------------------------------------- /examples/postgres/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: postgres 4 | restart: always 5 | environment: 6 | POSTGRES_DB: superset 7 | POSTGRES_PASSWORD: superset 8 | POSTGRES_USER: superset 9 | volumes: 10 | - postgres:/var/lib/postgresql 11 | redis: 12 | image: redis 13 | restart: always 14 | volumes: 15 | - redis:/data 16 | superset: 17 | image: amancevice/superset 18 | restart: always 19 | depends_on: 20 | - db 21 | - redis 22 | environment: 23 | MAPBOX_API_KEY: ${MAPBOX_API_KEY} 24 | ports: 25 | - "8088:8088" 26 | volumes: 27 | - ./superset_config.py:/etc/superset/superset_config.py 28 | volumes: 29 | postgres: 30 | redis: 31 | -------------------------------------------------------------------------------- /examples/mysql/superset_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | MAPBOX_API_KEY = os.getenv("MAPBOX_API_KEY", "") 4 | CACHE_CONFIG = { 5 | "CACHE_TYPE": "RedisCache", 6 | "CACHE_DEFAULT_TIMEOUT": 300, 7 | "CACHE_KEY_PREFIX": "superset_", 8 | "CACHE_REDIS_HOST": "redis", 9 | "CACHE_REDIS_PORT": 6379, 10 | "CACHE_REDIS_DB": 1, 11 | "CACHE_REDIS_URL": "redis://redis:6379/1", 12 | } 13 | FILTER_STATE_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_filter_"} 14 | EXPLORE_FORM_DATA_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_explore_form_"} 15 | SQLALCHEMY_DATABASE_URI = "mysql://superset:superset@db:3306/superset?charset=utf8mb4" 16 | SQLALCHEMY_TRACK_MODIFICATIONS = True 17 | SECRET_KEY = "thisISaSECRET_1234" 18 | -------------------------------------------------------------------------------- /examples/postgres/superset_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | MAPBOX_API_KEY = os.getenv("MAPBOX_API_KEY", "") 4 | CACHE_CONFIG = { 5 | "CACHE_TYPE": "RedisCache", 6 | "CACHE_DEFAULT_TIMEOUT": 300, 7 | "CACHE_KEY_PREFIX": "superset_", 8 | "CACHE_REDIS_HOST": "redis", 9 | "CACHE_REDIS_PORT": 6379, 10 | "CACHE_REDIS_DB": 1, 11 | "CACHE_REDIS_URL": "redis://redis:6379/1", 12 | } 13 | FILTER_STATE_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_filter_"} 14 | EXPLORE_FORM_DATA_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_explore_form_"} 15 | SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://superset:superset@db:5432/superset" 16 | SQLALCHEMY_TRACK_MODIFICATIONS = True 17 | SECRET_KEY = "thisISaSECRET_1234" 18 | -------------------------------------------------------------------------------- /examples/mysql/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 4 | image: mysql:8 5 | restart: always 6 | environment: 7 | MYSQL_DATABASE: superset 8 | MYSQL_PASSWORD: superset 9 | MYSQL_ROOT_PASSWORD: superset 10 | MYSQL_USER: superset 11 | volumes: 12 | - mysql:/var/lib/mysql 13 | redis: 14 | image: redis 15 | restart: always 16 | volumes: 17 | - redis:/data 18 | superset: 19 | image: amancevice/superset 20 | restart: always 21 | depends_on: 22 | - db 23 | - redis 24 | environment: 25 | MAPBOX_API_KEY: ${MAPBOX_API_KEY} 26 | ports: 27 | - "8088:8088" 28 | volumes: 29 | - ./superset_config.py:/etc/superset/superset_config.py 30 | volumes: 31 | mysql: 32 | redis: 33 | -------------------------------------------------------------------------------- /examples/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | stderr() { printf "$(tput setaf $1)$2$(tput sgr0)" "${*:3}" >&2 ; } 4 | execho() { stderr 240 "%s\n" "$*" ; eval "$@" ; } 5 | 6 | case $1 in 7 | celery | mysql | postgres | sqlite) ;; 8 | *) echo "Usage: ./demo.sh mysql|postgres|sqlite|celery" ; exit 1 ;; 9 | esac 10 | 11 | cd $1 12 | 13 | # Start back end 14 | if [ "$1" == "sqlite" ]; then 15 | execho docker compose up -d redis 16 | else 17 | execho docker compose up -d db redis 18 | execho sleep 10 19 | fi 20 | 21 | # Start Superset 22 | execho docker compose up -d superset 23 | if [ "$1" == 'celery' ]; then 24 | execho docker compose up -d worker 25 | fi 26 | execho sleep 10 27 | 28 | # Inititalize Demo 29 | execho docker compose exec superset superset-demo 30 | 31 | # Show message 32 | stderr 6 "%s\n" 'Navigate to http://localhost:8088 to view demo' 33 | stderr 6 "%s " 'Press RETURN to bring down demo' 34 | read 35 | execho docker compose down -v 36 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCH := linux/arm64 2 | REPO := amancevice/superset 3 | PYTHON_VERSION := $(shell cat .python-version) 4 | SUPERSET_VERSION := $(shell grep apache-superset Pipfile | grep -Eo '[0-9.]+') 5 | 6 | build: requirements-dev.txt 7 | docker buildx build \ 8 | --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ 9 | --platform $(ARCH) \ 10 | --tag $(REPO) \ 11 | --tag $(REPO):$(SUPERSET_VERSION) \ 12 | . 13 | 14 | clean: 15 | pipenv --rm 16 | docker image ls --quiet $(REPO) | uniq | xargs docker image rm --force 17 | 18 | push: 19 | docker push --all-tags $(REPO) 20 | 21 | .PHONY: build clean demo push 22 | 23 | requirements-dev.txt: requirements.txt 24 | pipenv requirements --dev > $@ 25 | 26 | requirements.txt: Pipfile.lock 27 | pipenv requirements > $@ 28 | 29 | Pipfile.lock: Pipfile | .venv 30 | pipenv lock 31 | 32 | .venv: .python-version 33 | -pipenv --rm 34 | mkdir -p $@ 35 | pipenv --python $(PYTHON_VERSION) 36 | touch $@ 37 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | apache-superset = "==6.0.0" 8 | cffi = "==1.17.1" 9 | 10 | [dev-packages] 11 | "infi.clickhouse-orm" = "==2.1.3" 12 | authlib = "==1.3.1" 13 | clickhouse-sqlalchemy = "==0.2.4" 14 | cx-oracle = "==8.3.0" 15 | # elasticsearch-dbapi = "==0.2.10" 16 | flask-cors = "==4.0.2" 17 | flask-mail = "==0.9.1" 18 | flask-oauth = "==0.12" 19 | flask-oauthlib = "==0.9.6" 20 | gevent = "==23.9.1" 21 | impyla = "==0.18.0" 22 | markupsafe = "==2.1.3" 23 | mysqlclient = "==2.2.0" 24 | openpyxl = "==3.1.2" 25 | pillow = "==10.3.0" 26 | prophet = "==1.1.5" 27 | psycopg2 = "==2.9.7" 28 | pyathena = "==3.12.2" 29 | pydruid = "==0.6.5" 30 | pyhive = "==0.7.0" 31 | pyldap = "==3.0.0" 32 | # pymssql-linux = "==2.1.6" 33 | # sasl = "==0.3.1" 34 | snowflake-sqlalchemy = "==1.7.3" 35 | sqlalchemy-bigquery = "==1.15.0" 36 | sqlalchemy-redshift = "==0.8.14" 37 | sqlalchemy-trino = "==0.5.0" 38 | thrift-sasl = "==0.4.3" 39 | -------------------------------------------------------------------------------- /examples/celery/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: postgres 4 | restart: always 5 | environment: 6 | POSTGRES_DB: superset 7 | POSTGRES_PASSWORD: superset 8 | POSTGRES_USER: superset 9 | volumes: 10 | - postgres:/var/lib/postgresql/data 11 | redis: 12 | image: redis 13 | restart: always 14 | volumes: 15 | - redis:/data 16 | superset: 17 | image: amancevice/superset 18 | restart: always 19 | depends_on: 20 | - postgres 21 | - redis 22 | environment: 23 | MAPBOX_API_KEY: ${MAPBOX_API_KEY} 24 | ports: 25 | - "8088:8088" 26 | volumes: 27 | - ./superset:/etc/superset 28 | worker: 29 | image: amancevice/superset 30 | restart: always 31 | depends_on: 32 | - db 33 | - redis 34 | environment: 35 | MAPBOX_API_KEY: ${MAPBOX_API_KEY} 36 | volumes: 37 | - ./superset:/etc/superset 38 | command: "celery worker --app=superset.tasks.celery_app:app" 39 | volumes: 40 | postgres: 41 | redis: 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Alexander Mancevice 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | name: push 2 | on: 3 | release: 4 | types: 5 | - published 6 | jobs: 7 | lint: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-node@v4 12 | - run: npm install -g dockerlint 13 | - run: dockerlint 14 | build-push: 15 | runs-on: ubuntu-latest 16 | needs: lint 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: docker/setup-qemu-action@v3 20 | - uses: docker/setup-buildx-action@v3 21 | - uses: docker/login-action@v3 22 | with: 23 | username: ${{ secrets.DOCKERHUB_USERNAME }} 24 | password: ${{ secrets.DOCKERHUB_TOKEN }} 25 | - name: meta 26 | id: meta 27 | run: | 28 | version="$(grep apache-superset Pipfile | grep -Eo '[0-9.]+')" 29 | tags="amancevice/superset,amancevice/superset:$version" 30 | echo "tags=$tags" >> "$GITHUB_OUTPUT" 31 | - uses: docker/build-push-action@v6 32 | with: 33 | platforms: | 34 | linux/amd64 35 | push: true 36 | tags: | 37 | ${{ steps.meta.outputs.tags }} 38 | -------------------------------------------------------------------------------- /examples/celery/superset/superset_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from cachelib import RedisCache 4 | 5 | 6 | MAPBOX_API_KEY = os.getenv("MAPBOX_API_KEY", "") 7 | CACHE_CONFIG = { 8 | "CACHE_TYPE": "RedisCache", 9 | "CACHE_DEFAULT_TIMEOUT": 300, 10 | "CACHE_KEY_PREFIX": "superset_", 11 | "CACHE_REDIS_HOST": "redis", 12 | "CACHE_REDIS_PORT": 6379, 13 | "CACHE_REDIS_DB": 1, 14 | "CACHE_REDIS_URL": "redis://redis:6379/1", 15 | } 16 | FILTER_STATE_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_filter_"} 17 | EXPLORE_FORM_DATA_CACHE_CONFIG = {**CACHE_CONFIG, "CACHE_KEY_PREFIX": "superset_explore_form_"} 18 | SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://superset:superset@db:5432/superset" 19 | SQLALCHEMY_TRACK_MODIFICATIONS = True 20 | SECRET_KEY = "thisISaSECRET_1234" 21 | 22 | 23 | class CeleryConfig(object): 24 | BROKER_URL = "redis://redis:6379/0" 25 | CELERY_IMPORTS = ("superset.sql_lab",) 26 | CELERY_RESULT_BACKEND = "redis://redis:6379/0" 27 | CELERY_ANNOTATIONS = {"tasks.add": {"rate_limit": "10/s"}} 28 | 29 | 30 | CELERY_CONFIG = CeleryConfig 31 | RESULTS_BACKEND = RedisCache(host="redis", port=6379, key_prefix="superset_results") 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTHON_VERSION=3.12 2 | FROM python:$PYTHON_VERSION 3 | 4 | # Configure environment 5 | # superset/gunicorn recommended defaults: 6 | # - https://superset.apache.org/docs/installation/configuring-superset#running-on-a-wsgi-http-server 7 | # - https://docs.gunicorn.org/en/latest/configure.html 8 | ENV FLASK_APP=superset 9 | ENV GUNICORN_BIND=0.0.0.0:8088 10 | ENV GUNICORN_LIMIT_REQUEST_FIELD_SIZE=8190 11 | ENV GUNICORN_LIMIT_REQUEST_LINE=4094 12 | ENV GUNICORN_THREADS=4 13 | ENV GUNICORN_TIMEOUT=120 14 | ENV GUNICORN_WORKERS=10 15 | ENV GUNICORN_WORKER_CLASS=gevent 16 | ENV LANG=C.UTF-8 17 | ENV LC_ALL=C.UTF-8 18 | ENV PYTHONPATH=/etc/superset:/home/superset 19 | ENV SUPERSET_HOME=/var/lib/superset 20 | ENV GUNICORN_CMD_ARGS="--bind $GUNICORN_BIND --limit-request-field_size $GUNICORN_LIMIT_REQUEST_FIELD_SIZE --limit-request-line $GUNICORN_LIMIT_REQUEST_LINE --threads $GUNICORN_THREADS --timeout $GUNICORN_TIMEOUT --workers $GUNICORN_WORKERS --worker-class $GUNICORN_WORKER_CLASS" 21 | 22 | # Configure filesystem 23 | COPY bin /usr/local/bin 24 | VOLUME /etc/superset 25 | VOLUME /home/superset 26 | VOLUME /var/lib/superset 27 | 28 | # Create superset user & install dependencies 29 | WORKDIR /home/superset 30 | RUN groupadd supergroup && \ 31 | useradd -U -G supergroup superset && \ 32 | mkdir -p $SUPERSET_HOME && \ 33 | mkdir -p /etc/superset && \ 34 | chown -R superset:superset $SUPERSET_HOME && \ 35 | chown -R superset:superset /home/superset && \ 36 | chown -R superset:superset /etc/superset && \ 37 | apt-get update && \ 38 | apt-get install -y \ 39 | build-essential \ 40 | curl \ 41 | default-libmysqlclient-dev \ 42 | freetds-bin \ 43 | freetds-dev \ 44 | libecpg-dev \ 45 | libffi-dev \ 46 | libldap2-dev \ 47 | libpq-dev \ 48 | libsasl2-2 \ 49 | libsasl2-dev \ 50 | libsasl2-modules-gssapi-mit \ 51 | libssl-dev && \ 52 | apt-get clean && \ 53 | pip install -U pip 54 | 55 | # Install pips 56 | COPY requirements*.txt ./ 57 | RUN pip install -r requirements.txt && \ 58 | pip install -r requirements-dev.txt 59 | 60 | # Configure application 61 | EXPOSE 8088 62 | USER superset 63 | HEALTHCHECK CMD ["curl", "-f", "http://localhost:8088/health"] 64 | CMD ["gunicorn", "superset.app:create_app()"] 65 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Superset Examples 2 | 3 | Example configurations for MySQL, PostgreSQL, SQLite, and Celery are provided, along with a simple demo script for starting them. 4 | 5 | Each demo provides a `superset_config.py` and a `docker-compose.yml`. Use these as guides for laying down your own instances. 6 | 7 | Start a demo of Superset using the `demo.sh` script. The script takes a single argument that determines the back end for Superset: `sqlite`, `mysql`, `postgres`, or `celery`. 8 | 9 | ```bash 10 | bash demo.sh mysql|postgres|sqlite|celery 11 | ``` 12 | 13 | You will be prompted to set up an admin user. 14 | 15 | When finished navigate to [http://localhost:8088/](http://localhost:8088/) to see the demo. 16 | 17 | Log in with the credentials you just created. 18 | 19 | The demo will live for 5 minutes and then be brought down. 20 | 21 | Here is a more detailed explanation of what the demo script is doing: 22 | 23 | ## MySQL 24 | 25 | ```bash 26 | cd mysql 27 | 28 | # Start Redis & MySQL services 29 | docker-compose up -d redis mysql 30 | # Wait for services to come up fully... 31 | 32 | # Start Superset 33 | docker-compose up -d superset 34 | # Wait for Superset to come up fully... 35 | 36 | # Initialize Superset DB 37 | docker-compose exec superset superset-demo 38 | # or `docker-compose exec superset superset-init` if no demo data needed 39 | 40 | # Play around in demo... 41 | 42 | # Bring everything down 43 | docker-compose down -v 44 | ``` 45 | 46 | ## PostgreSQL 47 | 48 | ```bash 49 | cd postgres 50 | 51 | # Start Redis & PostgreSQL services 52 | docker-compose up -d redis postgres 53 | # Wait for services to come up fully... 54 | 55 | # Start Superset 56 | docker-compose up -d superset 57 | # Wait for Superset to come up fully... 58 | 59 | # Initialize demo 60 | docker-compose exec superset superset-demo 61 | # or `docker-compose exec superset superset-init` if no demo data needed 62 | 63 | # Play around in demo... 64 | 65 | # Bring everything down 66 | docker-compose down -v 67 | ``` 68 | 69 | ## SQLite 70 | 71 | ```bash 72 | cd sqlite 73 | 74 | # Start Redis service 75 | docker-compose up -d redis 76 | # Wait for services to come up fully... 77 | 78 | # Touch SQLite db file 79 | mkdir -p superset 80 | touch superset/superset.db 81 | 82 | # Start Superset 83 | docker-compose up -d superset 84 | # Wait for Superset to come up fully... 85 | 86 | # Initialize demo 87 | docker-compose exec superset superset-demo 88 | # or `docker-compose exec superset superset-init` if no demo data needed 89 | 90 | # Play around in demo... 91 | 92 | # Bring everything down 93 | docker-compose down -v 94 | ``` 95 | 96 | ## Celery 97 | 98 | ```bash 99 | cd celery 100 | 101 | # Start Redis & PostgreSQL services 102 | docker-compose up -d redis postgres 103 | # Wait for services to come up fully... 104 | 105 | # Start Superset 106 | docker-compose up -d superset 107 | # Wait for Superset to come up fully... 108 | 109 | # Start Celery worker 110 | docker-compose up -d worker 111 | 112 | # Initialize demo 113 | docker-compose exec superset superset-demo 114 | # or `docker-compose exec superset superset-init` if no demo data needed 115 | 116 | # Play around in demo... 117 | 118 | # Bring everything down 119 | docker-compose down -v 120 | ``` 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Superset 2 | 3 | ![version](https://img.shields.io/docker/v/amancevice/superset?color=blue&label=version&logo=docker&logoColor=eee&sort=semver&style=flat-square) 4 | [![latest](https://img.shields.io/github/actions/workflow/status/amancevice/docker-superset/latest.yml?branch=main&label=latest&logo=github&style=flat-square)](https://github.com/amancevice/docker-superset/actions/workflows/latest.yml) 5 | 6 | Docker image for [Superset](https://github.com/ApacheInfra/superset). 7 | 8 | This project is unofficial and not related to Superset or Apache. 9 | 10 | ## Download 11 | 12 | Download this image from the Docker registry: 13 | 14 | ```bash 15 | docker pull amancevice/superset: 16 | ``` 17 | 18 | ## Building 19 | 20 | I **DO NOT** recommend building this image directly from the Dockerfile included in this repository. 21 | 22 | If you wish to extend this image then the best course of action is to write your own Dockerfile that extends this image. Eg, 23 | 24 | ```Dockerfile 25 | FROM amancevice/superset: 26 | USER root 27 | # Your changes... 28 | USER superset 29 | ``` 30 | 31 | ## Issues 32 | 33 | Please **ONLY** file issues in this project that are related to Docker and **DO** include the Docker commands or compose configuration of your setup when filing issues (be sure to hide any secrets/passwords before submitting). 34 | 35 | File issues/bugs with Superset at the [source](https://github.com/apache/superset). 36 | 37 | Please **DO NOT** files issues like "Please include `` in the Dockerfile," open a [pull request](https://github.com/amancevice/superset/pulls) for updates/enhancements. 38 | 39 | ## Examples 40 | 41 | Navigate to the [`examples`](./examples) directory to view examples of how to configure Superset with MySQL, PostgreSQL, or SQLite. 42 | 43 | ## Versions 44 | 45 | This repo is tagged in parallel with superset. Pulling `amancevice/superset:0.18.5` will fetch the image of this repository running superset version `0.18.5`. It is possible that the `latest` tag includes new features/support libraries but will usually be in sync with the latest semantic version. 46 | 47 | ## Configuration 48 | 49 | Follow the [instructions](https://superset.incubator.apache.org/installation.html#configuration) provided by Apache Superset for writing your own `superset_config.py`. Place this file in a local directory and mount this directory to `/etc/superset` inside the container. This location is included in the image's `PYTHONPATH`. Mounting this file to a different location is possible, but it will need to be in the `PYTHONPATH`. 50 | 51 | View the contents of the [`examples`](./examples) directory to see some simple `superset_config.py` samples. 52 | 53 | ## Volumes 54 | 55 | The image defines two data volumes: one for mounting configuration into the container, and one for data (logs, SQLite DBs, &c). 56 | 57 | The configuration volume is located alternatively at `/etc/superset` or `/home/superset`; either is acceptable. Both of these directories are included in the `PYTHONPATH` of the image. Mount any configuration (specifically the `superset_config.py` file) here to have it read by the app on startup. 58 | 59 | The data volume is located at `/var/lib/superset` and it is where you would mount your SQLite file (if you are using that as your backend), or a volume to collect any logs that are routed there. This location is used as the value of the `SUPERSET_HOME` environmental variable. 60 | 61 | ## Database Initialization 62 | 63 | After starting the Superset server, initialize the database with an admin user and Superset tables using the `superset-init` helper script: 64 | 65 | ```bash 66 | docker run --detach --name superset [options] amancevice/superset 67 | docker exec -it superset superset-init 68 | ``` 69 | 70 | ## Upgrading 71 | 72 | Upgrading to a newer version of superset can be accomplished by re-pulling `amancevice/superset`at a specified superset version or `latest` (see above for more on this). Remove the old container and re-deploy, making sure to use the correct environmental configuration. Finally, ensure the superset database is migrated up to the head: 73 | 74 | ```bash 75 | # Pull desired version 76 | docker pull amancevice/superset 77 | 78 | # Remove the current container 79 | docker rm -f superset-old 80 | 81 | # Deploy a new container ... 82 | docker run --detach --name superset-new [options] amancevice/superset 83 | 84 | # Upgrade the DB 85 | docker exec superset-new superset db upgrade 86 | 87 | # Sync the base permissions 88 | docker exec superset-new superset init 89 | ``` 90 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | alembic==1.17.2; python_version >= '3.10' 3 | amqp==5.3.1; python_version >= '3.6' 4 | apache-superset==6.0.0; python_version >= '3.10' 5 | apispec[yaml]==6.9.0; python_version >= '3.10' 6 | apsw==3.51.1.0; python_version >= '3.10' 7 | attrs==25.4.0; python_version >= '3.9' 8 | babel==2.17.0; python_version >= '3.8' 9 | backoff==2.2.1; python_version >= '3.7' and python_version < '4.0' 10 | backports.zstd==1.2.0; python_version < '3.14' and python_version >= '3.9' 11 | bcrypt==5.0.0; python_version >= '3.8' 12 | billiard==4.2.4; python_version >= '3.7' 13 | blinker==1.9.0; python_version >= '3.9' 14 | bottleneck==1.6.0; python_version >= '3.10' 15 | brotli==1.2.0; platform_python_implementation != 'PyPy' 16 | cachelib==0.13.0; python_version >= '3.8' 17 | cachetools==6.2.4; python_version >= '3.9' 18 | cattrs==25.3.0; python_version >= '3.9' 19 | celery==5.6.0; python_version >= '3.9' 20 | certifi==2025.11.12; python_version >= '3.7' 21 | cffi==1.17.1; python_version >= '3.8' 22 | charset-normalizer==3.4.4; python_version >= '3.7' 23 | click==8.3.1; python_version >= '3.10' 24 | click-didyoumean==0.3.1; python_full_version >= '3.6.2' 25 | click-option-group==0.5.9; python_version >= '3.7' 26 | click-plugins==1.1.1.2 27 | click-repl==0.3.0; python_version >= '3.6' 28 | colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' 29 | cron-descriptor==2.0.6; python_version >= '3.9' 30 | croniter==6.0.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' 31 | cryptography==44.0.3; python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1' 32 | defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' 33 | deprecated==1.3.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' 34 | deprecation==2.1.0 35 | dnspython==2.8.0; python_version >= '3.10' 36 | email-validator==2.3.0; python_version >= '3.8' 37 | et-xmlfile==2.0.0; python_version >= '3.8' 38 | exceptiongroup==1.3.1; python_version >= '3.7' 39 | flask==2.3.3; python_version >= '3.8' 40 | flask-appbuilder==5.0.2; python_version ~= '3.7' 41 | flask-babel==4.0.0; python_version >= '3.8' and python_version < '4.0' 42 | flask-caching==2.3.1; python_version >= '3.8' 43 | flask-compress==1.23; python_version >= '3.9' 44 | flask-cors==6.0.2; python_version >= '3.9' and python_version < '4.0' 45 | flask-jwt-extended==4.7.1; python_version >= '3.9' and python_version < '4' 46 | flask-limiter==3.12; python_version >= '3.10' 47 | flask-login==0.6.3; python_version >= '3.7' 48 | flask-migrate==3.1.0; python_version >= '3.6' 49 | flask-session==0.8.0; python_version >= '3.8' 50 | flask-sqlalchemy==3.0.5; python_version >= '3.7' 51 | flask-talisman==1.1.0 52 | flask-wtf==1.2.2; python_version >= '3.9' 53 | geographiclib==2.1; python_version >= '3.7' 54 | geopy==2.4.1; python_version >= '3.7' 55 | google-auth==2.45.0; python_version >= '3.7' 56 | greenlet==3.1.1; python_version >= '3.7' 57 | gunicorn==23.0.0; python_version >= '3.7' 58 | h11==0.16.0; python_version >= '3.8' 59 | hashids==1.3.1; python_version >= '2.7' 60 | holidays==0.87; python_version >= '3.10' 61 | humanize==4.14.0; python_version >= '3.10' 62 | idna==3.11; python_version >= '3.8' 63 | invoke==2.2.1; python_version >= '3.6' 64 | isodate==0.7.2; python_version >= '3.7' 65 | itsdangerous==2.2.0; python_version >= '3.8' 66 | jinja2==3.1.6; python_version >= '3.7' 67 | jsonpath-ng==1.7.0 68 | jsonschema==4.25.1; python_version >= '3.9' 69 | jsonschema-specifications==2025.9.1; python_version >= '3.9' 70 | kombu==5.6.1; python_version >= '3.9' 71 | limits==5.6.0; python_version >= '3.10' 72 | mako==1.3.10; python_version >= '3.8' 73 | markdown==3.10; python_version >= '3.10' 74 | markdown-it-py==4.0.0; python_version >= '3.10' 75 | markupsafe==3.0.3; python_version >= '3.9' 76 | marshmallow==3.26.1; python_version >= '3.9' 77 | marshmallow-sqlalchemy==1.4.2; python_version >= '3.9' 78 | mdurl==0.1.2; python_version >= '3.7' 79 | msgpack==1.0.8; python_version >= '3.8' 80 | msgspec==0.20.0; python_version >= '3.9' 81 | nh3==0.2.22; python_version >= '3.8' 82 | numpy==1.26.4; python_version >= '3.9' 83 | odfpy==1.4.1 84 | openpyxl==3.1.5; python_version >= '3.8' 85 | ordered-set==4.1.0; python_version >= '3.7' 86 | outcome==1.3.0.post0; python_version >= '3.7' 87 | packaging==25.0; python_version >= '3.8' 88 | pandas[excel]==2.1.4; python_version >= '3.9' 89 | paramiko==4.0.0; python_version >= '3.9' 90 | parsedatetime==2.6 91 | pgsanity==0.3.0; python_version >= '3.9' 92 | pillow==11.3.0; python_version >= '3.9' 93 | platformdirs==4.5.1; python_version >= '3.10' 94 | ply==3.11 95 | polyline==2.0.4; python_version >= '3.8' 96 | prison==0.2.1 97 | prompt-toolkit==3.0.52; python_version >= '3.8' 98 | pyarrow==18.1.0; python_version >= '3.9' 99 | pyasn1==0.6.1; python_version >= '3.8' 100 | pyasn1-modules==0.4.2; python_version >= '3.8' 101 | pycparser==2.23; python_version >= '3.8' 102 | pygments==2.19.2; python_version >= '3.8' 103 | pyjwt==2.10.1; python_version >= '3.9' 104 | pynacl==1.6.0; python_version >= '3.8' 105 | pyopenssl==25.1.0; python_version >= '3.7' 106 | pyparsing==3.2.5; python_version >= '3.9' 107 | pysocks==1.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' 108 | python-dateutil==2.9.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' 109 | python-dotenv==1.2.1; python_version >= '3.9' 110 | python-geohash==0.8.5 111 | pytz==2025.2 112 | pyxlsb==1.0.10 113 | pyyaml==6.0.3; python_version >= '3.8' 114 | redis==4.6.0; python_version >= '3.7' 115 | referencing==0.37.0; python_version >= '3.10' 116 | requests==2.32.5; python_version >= '3.9' 117 | requests-cache==1.2.1; python_version >= '3.8' 118 | rich==13.9.4; python_full_version >= '3.8.0' 119 | rpds-py==0.30.0; python_version >= '3.10' 120 | rsa==4.9.1; python_version >= '3.6' and python_version < '4' 121 | selenium==4.39.0; python_version >= '3.10' 122 | shillelagh[gsheetsapi]==1.4.3; python_version >= '3.9' 123 | simplejson==3.20.2; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2' 124 | six==1.17.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' 125 | slack-sdk==3.39.0; python_version >= '3.7' 126 | sniffio==1.3.1; python_version >= '3.7' 127 | sortedcontainers==2.4.0 128 | sqlalchemy==1.4.54; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' 129 | sqlalchemy-utils==0.38.3; python_version ~= '3.6' 130 | sqlglot==27.29.0; python_version >= '3.9' 131 | sshtunnel==0.4.0 132 | tabulate==0.9.0; python_version >= '3.7' 133 | trio==0.32.0; python_version >= '3.10' 134 | trio-websocket==0.12.2; python_version >= '3.8' 135 | typing-extensions==4.15.0; python_version >= '3.9' 136 | tzdata==2025.3; python_version >= '2' 137 | tzlocal==5.3.1; python_version >= '3.9' 138 | url-normalize==2.2.1; python_version >= '3.8' 139 | urllib3[socks]==2.6.2; python_version >= '3.9' 140 | vine==5.1.0; python_version >= '3.6' 141 | wcwidth==0.2.14; python_version >= '3.6' 142 | websocket-client==1.9.0; python_version >= '3.9' 143 | werkzeug==3.1.4; python_version >= '3.9' 144 | wrapt==2.0.1; python_version >= '3.8' 145 | wsproto==1.3.2; python_version >= '3.10' 146 | wtforms==3.2.1; python_version >= '3.9' 147 | wtforms-json==0.3.5 148 | xlrd==2.0.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' 149 | xlsxwriter==3.0.9; python_version >= '3.6' 150 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | asn1crypto==1.5.1 3 | asynch==0.3.1; python_version >= '3.9' and python_version < '4.0' 4 | authlib==1.3.1; python_version >= '3.8' 5 | bitarray==3.8.0 6 | blinker==1.9.0; python_version >= '3.9' 7 | boto3==1.42.14; python_version >= '3.9' 8 | botocore==1.42.14; python_version >= '3.9' 9 | cachelib==0.13.0; python_version >= '3.8' 10 | cachetools==6.2.4; python_version >= '3.9' 11 | certifi==2025.11.12; python_version >= '3.7' 12 | cffi==1.17.1; python_version >= '3.8' 13 | charset-normalizer==3.4.4; python_version >= '3.7' 14 | ciso8601==2.3.3 15 | click==8.3.1; python_version >= '3.10' 16 | clickhouse-driver==0.2.10; python_version >= '3.9' and python_version < '4' 17 | clickhouse-sqlalchemy==0.2.4; python_version >= '3.7' and python_version < '4' 18 | cmdstanpy==1.3.0; python_version >= '3.9' 19 | contourpy==1.3.3; python_version >= '3.11' 20 | cryptography==44.0.3; python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1' 21 | cx-oracle==8.3.0 22 | cycler==0.12.1; python_version >= '3.8' 23 | et-xmlfile==2.0.0; python_version >= '3.8' 24 | filelock==3.20.1; python_version >= '3.10' 25 | flask==2.3.3; python_version >= '3.8' 26 | flask-cors==6.0.2; python_version >= '3.9' and python_version < '4.0' 27 | flask-mail==0.9.1 28 | flask-oauth==0.12 29 | flask-oauthlib==0.9.6 30 | fonttools==4.61.1; python_version >= '3.10' 31 | fsspec==2025.12.0; python_version >= '3.10' 32 | future==1.0.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2' 33 | gevent==23.9.1; python_version >= '3.8' 34 | google-api-core[grpc]==2.28.1; python_version >= '3.7' 35 | google-auth==2.45.0; python_version >= '3.7' 36 | google-cloud-bigquery==3.39.0; python_version >= '3.9' 37 | google-cloud-core==2.5.0; python_version >= '3.7' 38 | google-crc32c==1.8.0; python_version >= '3.9' 39 | google-resumable-media==2.8.0; python_version >= '3.7' 40 | googleapis-common-protos==1.72.0; python_version >= '3.7' 41 | greenlet==3.1.1; python_version >= '3.7' 42 | grpcio==1.76.0; python_version >= '3.9' 43 | grpcio-status==1.76.0; python_version >= '3.9' 44 | holidays==0.87; python_version >= '3.10' 45 | httplib2==0.31.0; python_version >= '3.6' 46 | idna==3.11; python_version >= '3.8' 47 | importlib-resources==6.5.2; python_version >= '3.9' 48 | impyla==0.18.0 49 | infi.clickhouse-orm==2.1.3 50 | iso8601==2.1.0; python_version >= '3.7' and python_version < '4.0' 51 | itsdangerous==2.2.0; python_version >= '3.8' 52 | jinja2==3.1.6; python_version >= '3.7' 53 | jmespath==1.0.1; python_version >= '3.7' 54 | kiwisolver==1.4.9; python_version >= '3.10' 55 | leb128==1.0.8 56 | lz4==4.4.5; python_version >= '3.9' 57 | markupsafe==3.0.3; python_version >= '3.9' 58 | matplotlib==3.10.8; python_version >= '3.10' 59 | mysqlclient==2.2.0; python_version >= '3.8' 60 | numpy==1.26.4; python_version >= '3.9' 61 | oauth2==1.9.0.post1 62 | oauthlib==2.1.0 63 | openpyxl==3.1.5; python_version >= '3.8' 64 | orjson==3.11.5; python_version >= '3.9' 65 | packaging==25.0; python_version >= '3.8' 66 | pandas[excel]==2.1.4; python_version >= '3.9' 67 | pillow==11.3.0; python_version >= '3.9' 68 | platformdirs==4.5.1; python_version >= '3.10' 69 | prophet==1.1.5; python_version >= '3.7' 70 | proto-plus==1.27.0; python_version >= '3.7' 71 | protobuf==6.33.2; python_version >= '3.9' 72 | psycopg2==2.9.7; python_version >= '3.6' 73 | pure-sasl==0.6.2 74 | pyasn1==0.6.1; python_version >= '3.8' 75 | pyasn1-modules==0.4.2; python_version >= '3.8' 76 | pyathena==3.12.2; python_version >= '3.9' 77 | pycparser==2.23; python_version >= '3.8' 78 | pydruid==0.6.5 79 | pyhive==0.7.0 80 | pyjwt==2.10.1; python_version >= '3.9' 81 | pyldap==3.0.0 82 | pyopenssl==25.1.0; python_version >= '3.7' 83 | pyparsing==3.2.5; python_version >= '3.9' 84 | python-dateutil==2.9.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' 85 | python-ldap==3.4.5; python_version >= '3.6' 86 | pytz==2025.2 87 | requests==2.32.5; python_version >= '3.9' 88 | requests-oauthlib==1.1.0 89 | rsa==4.9.1; python_version >= '3.6' and python_version < '4' 90 | s3transfer==0.16.0; python_version >= '3.9' 91 | setuptools==80.9.0; python_version >= '3.9' 92 | six==1.17.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' 93 | snowflake-connector-python==3.18.0; python_version >= '3.9' 94 | snowflake-sqlalchemy==1.7.3; python_version >= '3.8' 95 | sortedcontainers==2.4.0 96 | sqlalchemy==1.4.54; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' 97 | sqlalchemy-bigquery==1.15.0; python_version < '3.14' and python_version >= '3.8' 98 | sqlalchemy-redshift==0.8.14; python_version >= '3.4' 99 | sqlalchemy-trino==0.5.0; python_version >= '3.7' 100 | stanio==0.5.1; python_version >= '3.8' 101 | tenacity==9.1.2; python_version >= '3.9' 102 | thrift==0.16.0 103 | thrift-sasl==0.4.3 104 | tomlkit==0.13.3; python_version >= '3.8' 105 | tqdm==4.67.1; python_version >= '3.7' 106 | trino[sqlalchemy]==0.336.0; python_version >= '3.9' 107 | typing-extensions==4.15.0; python_version >= '3.9' 108 | tzdata==2025.3; python_version >= '2' 109 | tzlocal==5.3.1; python_version >= '3.9' 110 | urllib3[socks]==2.6.2; python_version >= '3.9' 111 | werkzeug==3.1.4; python_version >= '3.9' 112 | zope.event==6.1; python_version >= '3.10' 113 | zope.interface==8.1.1; python_version >= '3.10' 114 | zstandard==0.25.0; python_version >= '3.9' 115 | zstd==1.5.7.2 116 | alembic==1.17.2; python_version >= '3.10' 117 | amqp==5.3.1; python_version >= '3.6' 118 | apache-superset==6.0.0; python_version >= '3.10' 119 | apispec[yaml]==6.9.0; python_version >= '3.10' 120 | apsw==3.51.1.0; python_version >= '3.10' 121 | attrs==25.4.0; python_version >= '3.9' 122 | babel==2.17.0; python_version >= '3.8' 123 | backoff==2.2.1; python_version >= '3.7' and python_version < '4.0' 124 | backports.zstd==1.2.0; python_version < '3.14' and python_version >= '3.9' 125 | bcrypt==5.0.0; python_version >= '3.8' 126 | billiard==4.2.4; python_version >= '3.7' 127 | bottleneck==1.6.0; python_version >= '3.10' 128 | brotli==1.2.0; platform_python_implementation != 'PyPy' 129 | cattrs==25.3.0; python_version >= '3.9' 130 | celery==5.6.0; python_version >= '3.9' 131 | click-didyoumean==0.3.1; python_full_version >= '3.6.2' 132 | click-option-group==0.5.9; python_version >= '3.7' 133 | click-plugins==1.1.1.2 134 | click-repl==0.3.0; python_version >= '3.6' 135 | colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' 136 | cron-descriptor==2.0.6; python_version >= '3.9' 137 | croniter==6.0.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' 138 | defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' 139 | deprecated==1.3.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' 140 | deprecation==2.1.0 141 | dnspython==2.8.0; python_version >= '3.10' 142 | email-validator==2.3.0; python_version >= '3.8' 143 | exceptiongroup==1.3.1; python_version >= '3.7' 144 | flask-appbuilder==5.0.2; python_version ~= '3.7' 145 | flask-babel==4.0.0; python_version >= '3.8' and python_version < '4.0' 146 | flask-caching==2.3.1; python_version >= '3.8' 147 | flask-compress==1.23; python_version >= '3.9' 148 | flask-jwt-extended==4.7.1; python_version >= '3.9' and python_version < '4' 149 | flask-limiter==3.12; python_version >= '3.10' 150 | flask-login==0.6.3; python_version >= '3.7' 151 | flask-migrate==3.1.0; python_version >= '3.6' 152 | flask-session==0.8.0; python_version >= '3.8' 153 | flask-sqlalchemy==3.0.5; python_version >= '3.7' 154 | flask-talisman==1.1.0 155 | flask-wtf==1.2.2; python_version >= '3.9' 156 | geographiclib==2.1; python_version >= '3.7' 157 | geopy==2.4.1; python_version >= '3.7' 158 | gunicorn==23.0.0; python_version >= '3.7' 159 | h11==0.16.0; python_version >= '3.8' 160 | hashids==1.3.1; python_version >= '2.7' 161 | humanize==4.14.0; python_version >= '3.10' 162 | invoke==2.2.1; python_version >= '3.6' 163 | isodate==0.7.2; python_version >= '3.7' 164 | jsonpath-ng==1.7.0 165 | jsonschema==4.25.1; python_version >= '3.9' 166 | jsonschema-specifications==2025.9.1; python_version >= '3.9' 167 | kombu==5.6.1; python_version >= '3.9' 168 | limits==5.6.0; python_version >= '3.10' 169 | mako==1.3.10; python_version >= '3.8' 170 | markdown==3.10; python_version >= '3.10' 171 | markdown-it-py==4.0.0; python_version >= '3.10' 172 | marshmallow==3.26.1; python_version >= '3.9' 173 | marshmallow-sqlalchemy==1.4.2; python_version >= '3.9' 174 | mdurl==0.1.2; python_version >= '3.7' 175 | msgpack==1.0.8; python_version >= '3.8' 176 | msgspec==0.20.0; python_version >= '3.9' 177 | nh3==0.2.22; python_version >= '3.8' 178 | odfpy==1.4.1 179 | ordered-set==4.1.0; python_version >= '3.7' 180 | outcome==1.3.0.post0; python_version >= '3.7' 181 | paramiko==4.0.0; python_version >= '3.9' 182 | parsedatetime==2.6 183 | pgsanity==0.3.0; python_version >= '3.9' 184 | ply==3.11 185 | polyline==2.0.4; python_version >= '3.8' 186 | prison==0.2.1 187 | prompt-toolkit==3.0.52; python_version >= '3.8' 188 | pyarrow==18.1.0; python_version >= '3.9' 189 | pygments==2.19.2; python_version >= '3.8' 190 | pynacl==1.6.0; python_version >= '3.8' 191 | pysocks==1.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' 192 | python-dotenv==1.2.1; python_version >= '3.9' 193 | python-geohash==0.8.5 194 | pyxlsb==1.0.10 195 | pyyaml==6.0.3; python_version >= '3.8' 196 | redis==4.6.0; python_version >= '3.7' 197 | referencing==0.37.0; python_version >= '3.10' 198 | requests-cache==1.2.1; python_version >= '3.8' 199 | rich==13.9.4; python_full_version >= '3.8.0' 200 | rpds-py==0.30.0; python_version >= '3.10' 201 | selenium==4.39.0; python_version >= '3.10' 202 | shillelagh[gsheetsapi]==1.4.3; python_version >= '3.9' 203 | simplejson==3.20.2; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2' 204 | slack-sdk==3.39.0; python_version >= '3.7' 205 | sniffio==1.3.1; python_version >= '3.7' 206 | sqlalchemy-utils==0.38.3; python_version ~= '3.6' 207 | sqlglot==27.29.0; python_version >= '3.9' 208 | sshtunnel==0.4.0 209 | tabulate==0.9.0; python_version >= '3.7' 210 | trio==0.32.0; python_version >= '3.10' 211 | trio-websocket==0.12.2; python_version >= '3.8' 212 | url-normalize==2.2.1; python_version >= '3.8' 213 | vine==5.1.0; python_version >= '3.6' 214 | wcwidth==0.2.14; python_version >= '3.6' 215 | websocket-client==1.9.0; python_version >= '3.9' 216 | wrapt==2.0.1; python_version >= '3.8' 217 | wsproto==1.3.2; python_version >= '3.10' 218 | wtforms==3.2.1; python_version >= '3.9' 219 | wtforms-json==0.3.5 220 | xlrd==2.0.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' 221 | xlsxwriter==3.0.9; python_version >= '3.6' 222 | --------------------------------------------------------------------------------