# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. [build-system] requires = ["setuptools>=40.9.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "apache-superset" description = "A modern, enterprise-ready business intelligence web application" readme = "README.md" dynamic = ["version", "scripts", "entry-points"] requires-python = "~=3.9" license = { file="LICENSE.txt" } authors = [ { name = "Apache Software Foundation", email = "dev@superset.apache.org" }, ] classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] dependencies = [ "backoff>=1.8.0", "celery>=5.3.6, <6.0.0", "click>=8.0.3", "click-option-group", "colorama", "croniter>=0.3.28", "cron-descriptor", "cryptography>=42.0.4, <43.0.0", "deprecation>=2.1.0, <2.2.0", "flask>=2.2.5, <3.0.0", "flask-appbuilder>=4.5.0, <5.0.0", "flask-caching>=2.1.0, <3", "flask-compress>=1.13, <2.0", "flask-talisman>=1.0.0, <2.0", "flask-login>=0.6.0, < 1.0", "flask-migrate>=3.1.0, <4.0", "flask-session>=0.4.0, <1.0", "flask-wtf>=1.1.0, <2.0", "func_timeout", "geopy", "gunicorn>=22.0.0; sys_platform != 'win32'", "hashids>=1.3.1, <2", "holidays>=0.25, <0.26", "humanize", "importlib_metadata", "isodate", "Mako>=1.2.2", "markdown>=3.0", "msgpack>=1.0.0, <1.1", "nh3>=0.2.11, <0.3", "numpy==1.23.5", "packaging", "pandas[performance]>=2.0.3, <2.1", "parsedatetime", "paramiko>=3.4.0", "pgsanity", "polyline>=2.0.0, <3.0", "pyparsing>=3.0.6, <4", "python-dateutil", "python-dotenv", "python-geohash", "pyarrow>=14.0.1, <15", "pyyaml>=6.0.0, <7.0.0", "PyJWT>=2.4.0, <3.0", "redis>=4.6.0, <5.0", "selenium>=3.141.0, <4.10.0", "shillelagh[gsheetsapi]>=1.2.18, <2.0", "shortid", "sshtunnel>=0.4.0, <0.5", "simplejson>=3.15.0", "slack_sdk>=3.19.0, <4", "sqlalchemy>=1.4, <2", "sqlalchemy-utils>=0.38.3, <0.39", "sqlglot>=23.0.2,<24", "sqlparse>=0.5.0", "tabulate>=0.8.9, <0.9", "typing-extensions>=4, <5", "waitress; sys_platform == 'win32'", "wtforms>=2.3.3, <4", "wtforms-json", "xlsxwriter>=3.0.7, <3.1", ] [project.optional-dependencies] athena = ["pyathena[pandas]>=2, <3"] aurora-data-api = ["preset-sqlalchemy-aurora-data-api>=0.2.8,<0.3"] bigquery = [ "pandas-gbq>=0.19.1", "sqlalchemy-bigquery>=1.6.1", "google-cloud-bigquery>=3.10.0", ] clickhouse = ["clickhouse-connect>=0.5.14, <1.0"] cockroachdb = ["cockroachdb>=0.3.5, <0.4"] cors = ["flask-cors>=2.0.0"] crate = ["crate[sqlalchemy]>=0.26.0, <0.27"] databend = ["databend-sqlalchemy>=0.3.2, <1.0"] databricks = [ "databricks-sql-connector>=2.0.2, <3", "sqlalchemy-databricks>=0.2.0", ] db2 = ["ibm-db-sa>0.3.8, <=0.4.0"] dremio = ["sqlalchemy-dremio>=1.1.5, <1.3"] drill = ["sqlalchemy-drill>=1.1.4, <2"] druid = ["pydruid>=0.6.5,<0.7"] duckdb = ["duckdb-engine>=0.9.5, <0.10"] dynamodb = ["pydynamodb>=0.4.2"] solr = ["sqlalchemy-solr >= 0.2.0"] elasticsearch = ["elasticsearch-dbapi>=0.2.9, <0.3.0"] exasol = ["sqlalchemy-exasol >= 2.4.0, <3.0"] excel = ["xlrd>=1.2.0, <1.3"] firebird = ["sqlalchemy-firebird>=0.7.0, <0.8"] firebolt = ["firebolt-sqlalchemy>=1.0.0, <2"] gevent = ["gevent>=23.9.1"] gsheets = ["shillelagh[gsheetsapi]>=1.2.18, <2"] hana = ["hdbcli==2.4.162", "sqlalchemy_hana==0.4.0"] hive = [ "boto3", "pyhive[hive]>=0.6.5;python_version<'3.11'", "pyhive[hive_pure_sasl]>=0.7.0", "tableschema", "thrift>=0.14.1, <1.0.0", "thrift_sasl>=0.4.3, < 1.0.0", ] impala = ["impyla>0.16.2, <0.17"] kusto = ["sqlalchemy-kusto>=2.0.0, <3"] kylin = ["kylinpy>=2.8.1, <2.9"] mssql = ["pymssql>=2.2.8, <3"] mysql = ["mysqlclient>=2.1.0, <3"] ocient = [ "sqlalchemy-ocient>=1.0.0", "pyocient>=1.0.15, <2", "shapely", "geojson", ] oracle = ["cx-Oracle>8.0.0, <8.1"] pinot = ["pinotdb>=0.3.3, <0.4"] playwright = ["playwright>=1.37.0, <2"] postgres = ["psycopg2-binary==2.9.6"] presto = ["pyhive[presto]>=0.6.5"] trino = ["boto3", "trino>=0.328.0"] prophet = ["prophet>=1.1.5, <2"] redshift = ["sqlalchemy-redshift>=0.8.1, <0.9"] rockset = ["rockset-sqlalchemy>=0.0.1, <1"] shillelagh = ["shillelagh[all]>=1.2.18, <2"] snowflake = ["snowflake-sqlalchemy>=1.2.4, <2"] spark = [ "pyhive[hive]>=0.6.5;python_version<'3.11'", "pyhive[hive_pure_sasl]>=0.7", "tableschema", "thrift>=0.14.1, <1", ] teradata = ["teradatasql>=16.20.0.23"] thumbnails = ["Pillow>=10.0.1, <11"] vertica = ["sqlalchemy-vertica-python>=0.5.9, < 0.6"] netezza = ["nzalchemy>=11.0.2"] starrocks = ["starrocks>=1.0.0"] doris = ["pydoris>=1.0.0, <2.0.0"] development = [ "docker", "flask-testing", "freezegun", "greenlet>=2.0.2", "grpcio>=1.55.3", "openapi-spec-validator", "parameterized", "pip-compile-multi", "pre-commit", "progress>=1.5,<2", "pyfakefs", "pyinstrument>=4.0.2,<5", "pylint", "pytest<8.0.0", # hairy issue with pytest >=8 where current_app proxies are not set in time "pytest-cov", "pytest-mock", "python-ldap>=3.4.4", "ruff", "sqloxide", "statsd", "tox", ] [project.urls] homepage = "https://superset.apache.org/" documentation = "https://superset.apache.org/docs/intro" [tool.isort] combine_as_imports = true include_trailing_comma = true line_length = 88 known_first_party = "superset" known_third_party = "alembic, apispec, backoff, celery, click, colorama, cron_descriptor, croniter, cryptography, dateutil, deprecation, flask, flask_appbuilder, flask_babel, flask_caching, flask_compress, flask_jwt_extended, flask_login, flask_migrate, flask_sqlalchemy, flask_talisman, flask_testing, flask_wtf, freezegun, geohash, geopy, holidays, humanize, isodate, jinja2, jwt, markdown, markupsafe, marshmallow, msgpack, nh3, numpy, pandas, parameterized, parsedatetime, pgsanity, pkg_resources, polyline, prison, progress, pyarrow, sqlalchemy_bigquery, pyhive, pyparsing, pytest, pytest_mock, pytz, redis, requests, selenium, setuptools, shillelagh, simplejson, slack, sqlalchemy, sqlalchemy_utils, sqlparse, typing_extensions, urllib3, werkzeug, wtforms, wtforms_json, yaml" multi_line_output = 3 order_by_type = false [tool.mypy] check_untyped_defs = true disallow_any_generics = true disallow_untyped_calls = true disallow_untyped_defs = true ignore_missing_imports = true no_implicit_optional = true warn_unused_ignores = true [[tool.mypy.overrides]] module = "superset.migrations.versions.*" ignore_errors = true [[tool.mypy.overrides]] module = "tests.*" check_untyped_defs = false disallow_untyped_calls = false disallow_untyped_defs = false [tool.tox] legacy_tox_ini = """ # Remember to start celery workers to run celery tests, e.g. # celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 [testenv] basepython = python3.10 ignore_basepython_conflict = true commands = superset db upgrade superset init # use -s to be able to use break pointers. # no args or tests/* can be passed as an argument to run all tests pytest -s {posargs} deps = -rrequirements/development.txt setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} mysql: SUPERSET__SQLALCHEMY_DATABASE_URI = mysql://mysqluser:mysqluserpassword@localhost/superset?charset=utf8 postgres: SUPERSET__SQLALCHEMY_DATABASE_URI = postgresql+psycopg2://superset:superset@localhost/test sqlite: SUPERSET__SQLALCHEMY_DATABASE_URI = sqlite:////{envtmpdir}/superset.db SUPERSET__SQLALCHEMY_EXAMPLES_URI = sqlite:////{envtmpdir}/examples.db mysql-presto: SUPERSET__SQLALCHEMY_DATABASE_URI = mysql://mysqluser:mysqluserpassword@localhost/superset?charset=utf8 # docker run -p 8080:8080 --name presto starburstdata/presto mysql-presto: SUPERSET__SQLALCHEMY_EXAMPLES_URI = presto://localhost:8080/memory/default # based on https://github.com/big-data-europe/docker-hadoop # clone the repo & run docker compose up -d to test locally mysql-hive: SUPERSET__SQLALCHEMY_DATABASE_URI = mysql://mysqluser:mysqluserpassword@localhost/superset?charset=utf8 mysql-hive: SUPERSET__SQLALCHEMY_EXAMPLES_URI = hive://localhost:10000/default # make sure that directory is accessible by docker hive: UPLOAD_FOLDER = /tmp/.superset/app/static/uploads/ usedevelop = true allowlist_externals = npm pkill [testenv:cypress] setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} commands = npm install -g npm@'>=6.5.0' pip install -e {toxinidir}/ {toxinidir}/superset-frontend/cypress_build.sh commands_post = pkill -if "python {envbindir}/flask" [testenv:cypress-dashboard] setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} commands = npm install -g npm@'>=6.5.0' pip install -e {toxinidir}/ {toxinidir}/superset-frontend/cypress_build.sh dashboard commands_post = pkill -if "python {envbindir}/flask" [testenv:cypress-explore] setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} commands = npm install -g npm@'>=6.5.0' pip install -e {toxinidir}/ {toxinidir}/superset-frontend/cypress_build.sh explore commands_post = pkill -if "python {envbindir}/flask" [testenv:cypress-sqllab] setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} commands = npm install -g npm@'>=6.5.0' pip install -e {toxinidir}/ {toxinidir}/superset-frontend/cypress_build.sh sqllab commands_post = pkill -if "python {envbindir}/flask" [testenv:cypress-sqllab-backend-persist] setenv = PYTHONPATH = {toxinidir} SUPERSET_TESTENV = true SUPERSET_CONFIG = tests.integration_tests.superset_test_config SUPERSET_HOME = {envtmpdir} commands = npm install -g npm@'>=6.5.0' pip install -e {toxinidir}/ {toxinidir}/superset-frontend/cypress_build.sh sqllab commands_post = pkill -if "python {envbindir}/flask" [testenv:eslint] changedir = {toxinidir}/superset-frontend commands = npm run lint deps = [testenv:fossa] commands = {toxinidir}/scripts/fossa.sh deps = passenv = * [testenv:javascript] commands = npm install -g npm@'>=6.5.0' {toxinidir}/superset-frontend/js_build.sh deps = [testenv:license-check] commands = {toxinidir}/scripts/check_license.sh passenv = * whitelist_externals = {toxinidir}/scripts/check_license.sh deps = [testenv:pre-commit] commands = pre-commit run --all-files deps = -rrequirements/development.txt skip_install = true [testenv:pylint] commands = pylint superset deps = -rrequirements/development.txt [testenv:thumbnails] setenv = SUPERSET_CONFIG = tests.integration_tests.superset_test_config_thumbnails deps = -rrequirements/development.txt [tox] envlist = cypress-dashboard cypress-explore cypress-sqllab cypress-sqllab-backend-persist eslint fossa javascript license-check pre-commit pylint skipsdist = true """ [tool.ruff] # Exclude a variety of commonly ignored directories. exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".git-rewrite", ".hg", ".ipynb_checkpoints", ".mypy_cache", ".nox", ".pants.d", ".pyenv", ".pytest_cache", ".pytype", ".ruff_cache", ".svn", ".tox", ".venv", ".vscode", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "site-packages", "venv", ] # Same as Black. line-length = 88 indent-width = 4 # Assume Python 3.8 target-version = "py310" [tool.ruff.lint] # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. select = [ "B904", "E4", "E7", "E9", "F", "TRY201", ] ignore = [] extend-select = ["I"] # Allow fix for all enabled rules (when `--fix`) is provided. fixable = ["ALL"] unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.lint.isort] case-sensitive = false combine-as-imports = true force-sort-within-sections = false known-first-party = [] known-third-party = [] lines-after-imports = -1 order-by-type = false section-order = [ "future", "standard-library", "third-party", "first-party", "local-folder" ] [tool.ruff.format] # Like Black, use double quotes for strings. quote-style = "double" # Like Black, indent with spaces, rather than tabs. indent-style = "space" # Like Black, respect magic trailing commas. skip-magic-trailing-comma = false # Like Black, automatically detect the appropriate line ending. line-ending = "auto" # Enable auto-formatting of code examples in docstrings. Markdown, # reStructuredText code/literal blocks and doctests are all supported. # # This is currently disabled by default, but it is planned for this # to be opt-out in the future. docstring-code-format = false # Set the line length limit used when formatting code snippets in # docstrings. # # This only has an effect when the `docstring-code-format` setting is # enabled. docstring-code-line-length = "dynamic"