Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support modern editable installs #2749

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ jobs:
name: 🏁 Build Component Packages & Update Dependencies/Artifacts
command: |
python -m venv venv && . venv/bin/activate
pip install --upgrade pip wheel setuptools
pip install --upgrade pip
set -eo pipefail
pip install -e .[ci,dev,testing,celery,diskcache] --progress-bar off
pip list | grep dash
npm ci
npm run build.sequential
python setup.py sdist
python -m build
mkdir dash-package && cp dist/*.tar.gz dash-package/dash-package.tar.gz
ls -la dash-package
no_output_timeout: 30m
Expand Down Expand Up @@ -159,13 +159,13 @@ jobs:
name: npm prereqs
command: |
npm ci
cd dash/dash-renderer && npm i && cd ../../
cd src/dash/dash-renderer && npm i && cd ../../../
cd components/dash-html-components && npm i && npm run extract && cd ../../
- run:
name: ️️🏗️ build dash
command: |
. venv/Scripts/activate
npm run private::build.jupyterlab && npm run private::build.renderer && python dash/development/update_components.py 'dash-html-components'
npm run private::build.jupyterlab && npm run private::build.renderer && python src/dash/development/update_components.py 'dash-html-components'
no_output_timeout: 30m

test-312: &test
Expand Down
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ ignore = C901, E203, E266, E501, E731, W503
select = B,C,E,F,W,T4
per-file-ignores =
tests/*: E722, F811
dash/html/I.py: E742
src/dash/html/I.py: E742
14 changes: 7 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ coverage.xml
# Distribution / packaging
.Python
build/
dash/deps/
dash/html/*
!dash/html/.gitkeep
dash/dcc/*
!dash/dcc/.gitkeep
dash/dash_table/*
!dash/dash_table/.gitkeep
src/dash/deps/
src/dash/html/*
!src/dash/html/.gitkeep
src/dash/dcc/*
!src/dash/dcc/.gitkeep
src/dash/dash_table/*
!src/dash/dash_table/.gitkeep
develop-eggs/
dist/
downloads/
Expand Down
6 changes: 3 additions & 3 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ ignore-patterns=

# Add files or directories matching the regex patterns to the ignore-list.
# The regex matches against paths.
ignore-paths=^dash/dcc/.*$,
^dash/html/.*$,
^dash/dash_table/.*$
ignore-paths=^src/dash/dcc/.*$,
^src/dash/html/.*$,
^src/dash/dash_table/.*$

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function getMetadata() {
const cp = child_process.spawn(
process.execPath,
[
path.resolve(__dirname, '..', '..', 'dash', 'extract-meta.js'),
path.resolve(__dirname, '..', '..', 'src', 'dash', 'extract-meta.js'),
'""', // ignore pattern
'^_.*$', // reserved keywords
path.join(__dirname, 'src', 'components')
Expand Down
6 changes: 3 additions & 3 deletions @plotly/dash-jupyterlab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
},
"scripts": {
"build": "tsc",
"build:pack": "jlpm run prepare && jlpm pack --filename ../../dash/labextension/dist/dash-jupyterlab.tgz && jlpm run build:copy",
"build:copy": "cp package.json ../../dash/labextension/dist/package.json",
"build:pack": "jlpm run prepare && jlpm pack --filename ../../src/dash/labextension/dist/dash-jupyterlab.tgz && jlpm run build:copy",
"build:copy": "cp package.json ../../src/dash/labextension/dist/package.json",
"clean": "rimraf lib",
"prepare": "mkdirp ../../dash/labextension/dist && jlpm run clean && jlpm run build",
"prepare": "mkdirp ../../src/dash/labextension/dist && jlpm run clean && jlpm run build",
"prettier": "prettier --write '{!(package),src/**,!(lib)/**}{.js,.jsx,.ts,.tsx,.css,.json,.md}'",
"watch": "tsc -w"
},
Expand Down
2 changes: 1 addition & 1 deletion MAKE_A_NEW_BACK_END.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ We also include a couple of files that are only used to generate the components:

Then we also have Python files. Most of these are generated directly from `metadata.json` - for example `Checklist.py` is a class definition corresponding to the Checklist React component, and if you look inside it you’ll see it inherits from the `dash.development.base_component.Component` class, it has a docstring listing all props and their types in Python notation (instead of “array of objects”, it says “list of dicts”), and it has a constructor that ensures you can only create it with appropriate props. Then there are some Python files that are NOT generated, but copied from https://github.com/plotly/dash-core-components/tree/master/dash_core_components_base - `__init__.py` collects all the component classes and explicitly lists all the browser assets in `_js_dist` and possibly `_css_dist`.

Each back end must have a way to generate its own wrappers for these React components. The Python wrappers are generated source code files as described above, created by [`_py_components_generation.py`](https://github.com/plotly/dash/blob/dev/dash/development/_py_components_generation.py) - other languages may choose to either generate files, or create precompiled objects of some sort, but the key requirements are:
Each back end must have a way to generate its own wrappers for these React components. The Python wrappers are generated source code files as described above, created by [`_py_components_generation.py`](https://github.com/plotly/dash/blob/dev/src/dash/development/_py_components_generation.py) - other languages may choose to either generate files, or create precompiled objects of some sort, but the key requirements are:
- Provide a natural way for users of this language to create components as data structures, keeping in mind that components may be nested inside the children prop of some other components, and most props are optional.
- To the extent that we can help users with built-in documentation and IDE auto-completion, we should try to do that.
- When requested by the framework, the component must serialize to JSON. This looks like:
Expand Down
22 changes: 11 additions & 11 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
include README.md
include LICENSE
include requires-*.txt
include dash/favicon.ico
include dash/extract-meta.js
include dash/deps/*.js
include dash/deps/*.map
include dash/dcc/*
include dash/html/*
include dash/dash_table/*
include dash/dash-renderer/build/*.js
include dash/dash-renderer/build/*.map
include dash/labextension/dist/dash-jupyterlab.tgz
include dash/labextension/package.json
include src/dash/favicon.ico
include src/dash/extract-meta.js
include src/dash/deps/*.js
include src/dash/deps/*.map
include src/dash/dcc/*
include src/dash/html/*
include src/dash/dash_table/*
include src/dash/dash-renderer/build/*.js
include src/dash/dash-renderer/build/*.map
include src/dash/labextension/dist/dash-jupyterlab.tgz
include src/dash/labextension/package.json
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
"license": "UNLICENSED",
"scripts": {
"private::format.black": "black dash tests --exclude metadata_test.py",
"private::format.renderer": "cd dash/dash-renderer && npm run format",
"private::format.renderer": "cd src/dash/dash-renderer && npm run format",
"private::format.dcc": "cd components/dash-core-components && npm run format",
"private::initialize.renderer": "cd dash/dash-renderer && npm ci",
"private::cibuild.components": "python dash/development/update_components.py 'all' --ci True",
"private::build.components": "python dash/development/update_components.py 'all'",
"private::cibuild.renderer": "cd dash/dash-renderer && renderer build",
"private::build.renderer": "cd dash/dash-renderer && renderer build",
"private::initialize.renderer": "cd src/dash/dash-renderer && npm ci",
"private::cibuild.components": "python src/dash/development/update_components.py 'all' --ci True",
"private::build.components": "python src/dash/development/update_components.py 'all'",
"private::cibuild.renderer": "cd src/dash/dash-renderer && renderer build",
"private::build.renderer": "cd src/dash/dash-renderer && renderer build",
"private::build.jupyterlab": "cd @plotly/dash-jupyterlab && jlpm install && jlpm build:pack",
"private::lint.black": "black dash tests --exclude metadata_test.py --check",
"private::lint.flake8": "flake8 --exclude=metadata_test.py dash tests",
"private::lint.pylint-dash": "pylint dash setup.py --rcfile=.pylintrc",
"private::lint.black": "black src tests --exclude metadata_test.py --check",
"private::lint.flake8": "flake8 --exclude=metadata_test.py src tests",
"private::lint.pylint-dash": "pylint src --rcfile=.pylintrc",
"private::lint.pylint-tests": "pylint tests/unit tests/integration -d all -e C0410,C0413,W0109 --rcfile=.pylintrc",
"private::lint.renderer": "cd dash/dash-renderer && npm run lint",
"private::lint.renderer": "cd src/dash/dash-renderer && npm run lint",
"private::test.setup-components": "cd @plotly/dash-test-components && npm ci && npm run build",
"private::test.setup-nested": "cd @plotly/dash-generator-test-component-nested && npm ci && npm run build",
"private::test.setup-standard": "cd @plotly/dash-generator-test-component-standard && npm ci && npm run build",
Expand All @@ -28,7 +28,7 @@
"private::test.R.deploy-nested": "npm run private::test.setup-nested && cd @plotly/dash-generator-test-component-nested && sudo R CMD INSTALL .",
"private::test.R.deploy-standard": "npm run private::test.setup-standard && cd @plotly/dash-generator-test-component-standard && sudo R CMD INSTALL .",
"private::test.unit-dash": "pytest tests/unit",
"private::test.unit-renderer": "cd dash/dash-renderer && npm run test",
"private::test.unit-renderer": "cd src/dash/dash-renderer && npm run test",
"private::test.unit-generation": "cd @plotly/dash-generator-test-component-typescript && npm ci && npm test",
"private::test.integration-dash": "TESTFILES=$(circleci tests glob \"tests/integration/**/test_*.py\" | circleci tests split --split-by=timings) && pytest --headless --nopercyfinalize --junitxml=test-reports/junit_intg.xml ${TESTFILES}",
"private::test.integration-dash-import": "cd tests/integration/dash && python dash_import_test.py",
Expand All @@ -43,8 +43,8 @@
"setup-tests.R": "run-s private::test.R.deploy-*",
"citest.integration": "run-s setup-tests.py private::test.integration-*",
"citest.unit": "run-s private::test.unit-**",
"test": "pytest && cd dash/dash-renderer && npm run test",
"first-build": "cd dash/dash-renderer && npm i && cd ../../ && cd components/dash-html-components && npm i && npm run extract && cd ../../ && npm run build"
"test": "pytest && cd src/dash/dash-renderer && npm run test",
"first-build": "cd src/dash/dash-renderer && npm i && cd ../../ && cd components/dash-html-components && npm i && npm run extract && cd ../../ && npm run build"
},
"devDependencies": {
"@lerna/filter-options": "^6.4.1",
Expand Down
81 changes: 81 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[build-system]
requires = ["setuptools>=61.2"]
build-backend = "setuptools.build_meta"

[project]
name = "dash"
authors = [{name = "Chris Parmer", email = "[email protected]"}]
license = {text = "MIT"}
description = "A Python framework for building reactive web-apps. Developed by Plotly."
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Dash",
"Framework :: Flask",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Financial and Insurance Industry",
"Intended Audience :: Healthcare Industry",
"Intended Audience :: Manufacturing",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Database :: Front-Ends",
"Topic :: Office/Business :: Financial :: Spreadsheet",
"Topic :: Scientific/Engineering :: Visualization",
"Topic :: Software Development :: Libraries :: Application Frameworks",
"Topic :: Software Development :: Widget Sets",
]
requires-python = ">=3.8"
dynamic = ["version", "dependencies", "optional-dependencies"]

[project.readme]
file = "README.md"
content-type = "text/markdown"

[project.urls]
Homepage = "https://plotly.com/dash"
Documentation = "https://dash.plotly.com"
Source = "https://github.com/plotly/dash"
"Issue Tracker" = "https://github.com/plotly/dash/issues"

[project.entry-points]
pytest11 = {dash = "dash.testing.plugin"}

[project.scripts]
dash-generate-components = "dash.development.component_generator:cli"
renderer = "dash.development.build_process:renderer"
dash-update-components = "dash.development.update_components:cli"

[tool.setuptools]
include-package-data = true

[tool.setuptools.dynamic]
version = {attr = "dash.version.__version__"}
dependencies = { file = "requires-install.txt"}

[tool.setuptools.dynamic.optional-dependencies]
ci = { file = "requires-ci.txt" }
dev = { file = "requires-dev.txt" }
testing = { file = "requires-testing.txt" }
celery = { file = "requires-celery.txt" }
diskcache = { file = "requires-diskcache.txt" }
compress = { file = "requires-compress.txt" }

[tool.setuptools.packages.find]
namespaces = false
where = ["src"]

[tool.setuptools.data-files]
# like `jupyter nbextension install --sys-prefix`
"share/jupyter/nbextensions/dash" = ["src/dash/nbextension/main.js"]
# like `jupyter nbextension enable --sys-prefix`
"etc/jupyter/nbconfig/notebook.d" = ["src/dash/nbextension/dash.json"]
# Place jupyterlab extension in extension directory
"share/jupyter/lab/extensions" = ["src/dash/labextension/dist/dash-jupyterlab.tgz"]
1 change: 1 addition & 0 deletions requires-ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ pyzmq==25.1.2
xlrd>=2.0.1
pytest-rerunfailures
jupyterlab<4.0.0
build==1.0.3
92 changes: 0 additions & 92 deletions setup.py

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
from setuptools import setup

with open("package.json") as fp:
with open("package.json", "rb") as fp:
package = json.load(fp)

setup(
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def build_components(components_source, concurrency):

dest_dir = dest_dir_map.get(package) or package

dest_path = os.path.join("dash", dest_dir)
dest_path = os.path.join("src", "dash", dest_dir)

if not os.path.exists(dest_path):
try:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion tests/integration/dash/dash_import_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
assert isinstance(dash, types.ModuleType), "dash can be imported"

this_dir = os.path.dirname(__file__)
with open(os.path.join(this_dir, "../../../dash/version.py")) as fp:
with open(os.path.join(this_dir, "../../../src/dash/version.py")) as fp:
assert dash.__version__ in fp.read(), "version is consistent"

assert getattr(dash, "Dash").__name__ == "Dash", "access to main Dash class is valid"