From c2968ba95b421fdc19cd49cb3fb407ff89ed7540 Mon Sep 17 00:00:00 2001 From: Jannic <37243923+jmholzer@users.noreply.github.com> Date: Thu, 30 Mar 2023 10:35:30 +0100 Subject: [PATCH 1/6] Reorganise the documentation structure for Kedro / Databricks integration (#2442) * Remove visualization docs from deployment section Signed-off-by: Jannic Holzer * Add new directory and new visualization docs Signed-off-by: Jannic Holzer * Remove old deployment docs Signed-off-by: Jannic Holzer * Add deployment docs to new directory Signed-off-by: Jannic Holzer * Modify spelling of visualize to British English 'visualise' Signed-off-by: Jannic Holzer * Add new documentation to index Signed-off-by: Jannic Holzer * Fix lint Signed-off-by: Jannic Holzer * Modify title of deployment guide Signed-off-by: Jannic Holzer * Remove spurious max depth to test if docs build Signed-off-by: Jannic Holzer * Refactor index.rst to try to avoid build failing Signed-off-by: Jannic Holzer * Modify call to sphinx-build to test if RTD will work Signed-off-by: Jannic Holzer * Revise index.rst Signed-off-by: Jo Stichbury * Lint and resolve Signed-off-by: Jo Stichbury Signed-off-by: Jannic Holzer * Change title to include mention of Notebooks Signed-off-by: Jannic Holzer * Remove verbosity from viz on Databricks intro Signed-off-by: Jannic Holzer * Revert command modifcation Signed-off-by: Jannic Holzer * Rename databricks visualisation docs Signed-off-by: Jannic Holzer * Add a line between copy and code snippets for rendering Co-authored-by: Jo Stichbury Signed-off-by: Jannic Holzer * Remove gerund Co-authored-by: Jo Stichbury Signed-off-by: Jannic Holzer * Remove spurious 'i.e.' Co-authored-by: Jo Stichbury Signed-off-by: Jannic Holzer * Rename workflow_integration to integrations Signed-off-by: Jannic Holzer * Rename index entry to 'Integrations' Signed-off-by: Jannic Holzer * Convert databricks.rst to MyST format Signed-off-by: Jannic Holzer * Rename databricks.rst to databricks.md Signed-off-by: Jannic Holzer * Remove spurious conflict messages Signed-off-by: Jannic Holzer --------- Signed-off-by: Jannic Holzer Signed-off-by: Jo Stichbury Co-authored-by: Jo Stichbury --- docs/source/deployment/deployment_guide.md | 1 - docs/source/index.rst | 23 +++++++++++++++++-- docs/source/integrations/databricks.md | 9 ++++++++ .../integrations/databricks_visualisation.md | 12 ++++++++++ .../databricks_workspace.md} | 12 +--------- docs/source/integrations/pyspark.rst | 9 ++++++++ .../pyspark_integration.md} | 0 7 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 docs/source/integrations/databricks.md create mode 100644 docs/source/integrations/databricks_visualisation.md rename docs/source/{deployment/databricks.md => integrations/databricks_workspace.md} (95%) create mode 100644 docs/source/integrations/pyspark.rst rename docs/source/{tools_integration/pyspark.md => integrations/pyspark_integration.md} (100%) diff --git a/docs/source/deployment/deployment_guide.md b/docs/source/deployment/deployment_guide.md index e940df8d46..468c8ff375 100644 --- a/docs/source/deployment/deployment_guide.md +++ b/docs/source/deployment/deployment_guide.md @@ -15,7 +15,6 @@ We also provide information to help you deploy to the following: * to [Prefect](prefect.md) * to [Kubeflow Workflows](kubeflow.md) * to [AWS Batch](aws_batch.md) -* to [Databricks](databricks.md) * to [Dask](dask.md) diff --git a/docs/source/index.rst b/docs/source/index.rst index 707c205748..391ec1edc0 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -152,6 +152,13 @@ Welcome to Kedro's documentation! logging/logging +.. toctree:: + :maxdepth: 2 + :caption: Integrations + + integrations/databricks.rst + integrations/pyspark.rst + .. toctree:: :maxdepth: 2 :caption: Development @@ -174,12 +181,17 @@ Welcome to Kedro's documentation! deployment/prefect deployment/kubeflow deployment/aws_batch - deployment/databricks deployment/aws_sagemaker deployment/aws_step_functions deployment/airflow_astronomer deployment/dask +.. toctree:: + :maxdepth: 2 + :caption: Databricks integration + + databricks_integration/visualisation + .. toctree:: :maxdepth: 2 :caption: PySpark integration @@ -188,9 +200,16 @@ Welcome to Kedro's documentation! .. toctree:: :maxdepth: 2 - :caption: Resources + :caption: FAQs faq/faq + faq/architecture_overview + faq/kedro_principles + +.. toctree:: + :maxdepth: 2 + :caption: Resources + resources/glossary diff --git a/docs/source/integrations/databricks.md b/docs/source/integrations/databricks.md new file mode 100644 index 0000000000..cc92f543fa --- /dev/null +++ b/docs/source/integrations/databricks.md @@ -0,0 +1,9 @@ +# Databricks integration + +```{toctree} +:caption: Databricks +:maxdepth: 2 + +databricks_workspace.md +visualisation.md +``` diff --git a/docs/source/integrations/databricks_visualisation.md b/docs/source/integrations/databricks_visualisation.md new file mode 100644 index 0000000000..e913f54ba0 --- /dev/null +++ b/docs/source/integrations/databricks_visualisation.md @@ -0,0 +1,12 @@ +# How to run Kedro-Viz on Databricks + +[Kedro-Viz](../visualisation/kedro-viz_visualisation.md) is a tool that allows you to visualise your Kedro pipeline. It is a standalone web application that runs on a web browser, it can be run on a local machine or on Databricks itself. + +For Kedro-Viz to run with your Kedro project, you need to ensure that both the packages are installed in the same scope (notebook-scoped vs. cluster library). This means that if you `%pip install kedro` from inside your notebook then you should also `%pip install kedro-viz` from inside your notebook. +If your cluster comes with Kedro installed on it as a library already then you should also add Kedro-Viz as a [cluster library](https://docs.microsoft.com/en-us/azure/databricks/libraries/cluster-libraries). + +Kedro-Viz can then be launched in a new browser tab with the `%run_viz` line magic: + +```ipython +In [2]: %run_viz +``` diff --git a/docs/source/deployment/databricks.md b/docs/source/integrations/databricks_workspace.md similarity index 95% rename from docs/source/deployment/databricks.md rename to docs/source/integrations/databricks_workspace.md index 4c9195c2b9..dd99ef92be 100644 --- a/docs/source/deployment/databricks.md +++ b/docs/source/integrations/databricks_workspace.md @@ -1,4 +1,4 @@ -# Deployment to a Databricks cluster +# Develop a project with Databricks Workspace and Notebooks This tutorial uses the [PySpark Iris Kedro Starter](https://github.com/kedro-org/kedro-starters/tree/main/pyspark-iris) to illustrate how to bootstrap a Kedro project using Spark and deploy it to a [Databricks cluster on AWS](https://databricks.com/aws). @@ -252,16 +252,6 @@ You must explicitly upgrade your `pip` version by doing the below: After this, you can reload Kedro by running the line magic command `%reload_kedro `. -### 10. Running Kedro-Viz on Databricks - -For Kedro-Viz to run with your Kedro project, you need to ensure that both the packages are installed in the same scope (notebook-scoped vs. cluster library). i.e. if you `%pip install kedro` from inside your notebook then you should also `%pip install kedro-viz` from inside your notebook. -If your cluster comes with Kedro installed on it as a library already then you should also add Kedro-Viz as a [cluster library](https://docs.microsoft.com/en-us/azure/databricks/libraries/cluster-libraries). - -Kedro-Viz can then be launched in a new browser tab with the `%run_viz` line magic: -```ipython -In [2]: %run_viz -``` - ## How to use datasets stored on Databricks DBFS DBFS is a distributed file system mounted into a DataBricks workspace and accessible on a DataBricks cluster. It maps cloud object storage URIs to relative paths so as to simplify the process of persisting files. With DBFS, libraries can read from or write to distributed storage as if it's a local file. diff --git a/docs/source/integrations/pyspark.rst b/docs/source/integrations/pyspark.rst new file mode 100644 index 0000000000..b7c4cf97fe --- /dev/null +++ b/docs/source/integrations/pyspark.rst @@ -0,0 +1,9 @@ + +PySpark integration +============================================= + +.. toctree:: + :maxdepth: 2 + :caption: PySpark + + pyspark_integration.md diff --git a/docs/source/tools_integration/pyspark.md b/docs/source/integrations/pyspark_integration.md similarity index 100% rename from docs/source/tools_integration/pyspark.md rename to docs/source/integrations/pyspark_integration.md From 38dfe6f5e9d2e8758a732044267769aafb1ff465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Cano=20Rodr=C3=ADguez?= Date: Thu, 30 Mar 2023 14:33:57 +0200 Subject: [PATCH 2/6] Initial Sphinx revamp (#2459) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove unused docs/package.json Nowadays sphinx-autobuild offers similar functionality. Signed-off-by: Juan Luis Cano Rodríguez * Fix Sphinx language config Signed-off-by: Juan Luis Cano Rodríguez * Fix circular imports Signed-off-by: Juan Luis Cano Rodríguez * Remove unused documentation extensions Signed-off-by: Juan Luis Cano Rodríguez * Try to not move files around Signed-off-by: Juan Luis Cano Rodríguez * Fix CSS paths Signed-off-by: Juan Luis Cano Rodríguez * Fix file hierarchy Signed-off-by: Juan Luis Cano Rodríguez * Fix Read the Docs configuration Signed-off-by: Juan Luis Cano Rodríguez * Update documentation dependencies Signed-off-by: Juan Luis Cano Rodríguez * Manually fix JupyterCommandGroup API docs See gh-2453. Signed-off-by: Juan Luis Cano Rodríguez * Install all documentation dependencies Signed-off-by: Juan Luis Cano Rodríguez * Restore test requirements kedro.extras.datasets is still being tested. Signed-off-by: Juan Luis Cano Rodríguez * Remove all autosummary members from problematic class See gh-2453. Signed-off-by: Juan Luis Cano Rodríguez * Temporarily disable nitpicky mode for linkcheck Signed-off-by: Juan Luis Cano Rodríguez * Upgrade Read the Docs to Python 3.8 Signed-off-by: Juan Luis Cano Rodríguez * Fix destination of linkcheck Signed-off-by: Juan Luis Cano Rodríguez * Minor fixes to docstrings Signed-off-by: Juan Luis Cano Rodríguez * Minor reference fix Signed-off-by: Juan Luis Cano Rodríguez * Cap sphinx-autodoc-typehints version Signed-off-by: Juan Luis Cano Rodríguez * Restore nitpicky linkcheck Signed-off-by: Juan Luis Cano Rodríguez * Restore treating documentation warnings as errors Signed-off-by: Juan Luis Cano Rodríguez * Remove redundant build-docs CI job Signed-off-by: Juan Luis Cano Rodríguez * Ignore .rst files generated to support docs build Signed-off-by: Jo Stichbury * Explain ignored documentation files Signed-off-by: Juan Luis Cano Rodríguez * Move linkcheck to Read the Docs Signed-off-by: Juan Luis Cano Rodríguez * Remove old devserver Makefile target Signed-off-by: Juan Luis Cano Rodríguez * Fix databricks broken reference Signed-off-by: Juan Luis Cano Rodríguez * Fix pyspark broken reference Signed-off-by: Juan Luis Cano Rodríguez * Fix other broken references Signed-off-by: Juan Luis Cano Rodríguez --------- Signed-off-by: Juan Luis Cano Rodríguez Signed-off-by: Jo Stichbury Co-authored-by: Jo Stichbury --- .circleci/continue_config.yml | 53 ------------------- .gitignore | 5 ++ .readthedocs.yml | 8 +-- Makefile | 3 -- docs/build-docs.sh | 29 ++-------- docs/package.json | 16 ------ .../{ => _static}/css/qb1-sphinx-rtd.css | 0 .../{ => _static}/css/theme-overrides.css | 0 .../_templates/autosummary/base.rst | 0 .../_templates/autosummary/class.rst | 0 .../_templates/autosummary/module.rst | 0 docs/{ => source}/_templates/breadcrumbs.html | 0 docs/{ => source}/_templates/layout.html | 0 docs/{ => source}/conf.py | 43 ++------------- .../development_for_databricks.md | 2 +- docs/source/index.rst | 21 +------- docs/source/integrations/databricks.md | 2 +- docs/source/integrations/pyspark.md | 8 +++ docs/source/integrations/pyspark.rst | 9 ---- docs/source/{api_docs => }/kedro.config.rst | 0 docs/source/{api_docs => }/kedro.datasets.rst | 0 .../{api_docs => }/kedro.extras.datasets.rst | 0 ...tras.logging.color_logger.ColorHandler.rst | 0 .../kedro.framework.cli.cli.KedroCLI.rst | 0 ...work.cli.hooks.manager.CLIHooksManager.rst | 0 ...mework.cli.jupyter.JupyterCommandGroup.rst | 10 ++++ ....framework.cli.utils.CommandCollection.rst | 0 .../kedro.framework.cli.utils.rst | 0 .../kedro.framework.context.rst | 0 ...mework.session.shelvestore.ShelveStore.rst | 0 ...amework.session.store.BaseSessionStore.rst | 0 docs/source/{api_docs => }/kedro.io.rst | 0 docs/source/{api_docs => }/kedro.pipeline.rst | 0 docs/source/{api_docs => }/kedro.runner.rst | 0 docs/{ => source}/kedro_logo.svg | 0 docs/source/kedro_project_setup/starters.md | 4 +- .../nodes_and_pipelines/run_a_pipeline.md | 2 +- docs/{ => source}/puppeteer-config.json | 0 docs/{ => source}/robots.txt | 0 docs/source/tutorial/add_another_pipeline.md | 2 +- docs/source/tutorial/package_a_project.md | 2 +- kedro/config/common.py | 2 +- kedro/config/config.py | 2 +- kedro/config/omegaconf_config.py | 2 +- kedro/config/templated_config.py | 2 +- kedro/io/__init__.py | 3 +- kedro/pipeline/modular_pipeline.py | 2 +- setup.py | 19 ++++--- 48 files changed, 61 insertions(+), 190 deletions(-) delete mode 100644 docs/package.json rename docs/source/{ => _static}/css/qb1-sphinx-rtd.css (100%) rename docs/source/{ => _static}/css/theme-overrides.css (100%) rename docs/{ => source}/_templates/autosummary/base.rst (100%) rename docs/{ => source}/_templates/autosummary/class.rst (100%) rename docs/{ => source}/_templates/autosummary/module.rst (100%) rename docs/{ => source}/_templates/breadcrumbs.html (100%) rename docs/{ => source}/_templates/layout.html (100%) rename docs/{ => source}/conf.py (92%) create mode 100644 docs/source/integrations/pyspark.md delete mode 100644 docs/source/integrations/pyspark.rst rename docs/source/{api_docs => }/kedro.config.rst (100%) rename docs/source/{api_docs => }/kedro.datasets.rst (100%) rename docs/source/{api_docs => }/kedro.extras.datasets.rst (100%) rename docs/source/{api_docs => }/kedro.extras.logging.color_logger.ColorHandler.rst (100%) rename docs/source/{api_docs => }/kedro.framework.cli.cli.KedroCLI.rst (100%) rename docs/source/{api_docs => }/kedro.framework.cli.hooks.manager.CLIHooksManager.rst (100%) create mode 100644 docs/source/kedro.framework.cli.jupyter.JupyterCommandGroup.rst rename docs/source/{api_docs => }/kedro.framework.cli.utils.CommandCollection.rst (100%) rename docs/source/{api_docs => }/kedro.framework.cli.utils.rst (100%) rename docs/source/{api_docs => }/kedro.framework.context.rst (100%) rename docs/source/{api_docs => }/kedro.framework.session.shelvestore.ShelveStore.rst (100%) rename docs/source/{api_docs => }/kedro.framework.session.store.BaseSessionStore.rst (100%) rename docs/source/{api_docs => }/kedro.io.rst (100%) rename docs/source/{api_docs => }/kedro.pipeline.rst (100%) rename docs/source/{api_docs => }/kedro.runner.rst (100%) rename docs/{ => source}/kedro_logo.svg (100%) rename docs/{ => source}/puppeteer-config.json (100%) rename docs/{ => source}/robots.txt (100%) diff --git a/.circleci/continue_config.yml b/.circleci/continue_config.yml index 55ed688e27..48407c0a3d 100644 --- a/.circleci/continue_config.yml +++ b/.circleci/continue_config.yml @@ -354,34 +354,6 @@ jobs: name: Pip-compile requirements file command: conda activate kedro_builder; make pip-compile - build_docs: - executor: - name: docker - python_version: "3.7" - steps: - - setup - - run: - name: Build docs - command: make build-docs - - run: - name: Pip freeze including docs dependencies - command: pip freeze - when: always - - docs_linkcheck: - executor: - name: docker - python_version: "3.8" - steps: - - setup - - run: - name: Check for broken links - command: make linkcheck - - run: - name: Pip freeze including docs dependencies - command: pip freeze - when: always - sync: docker: # https://circleci.com/docs/2.0/circleci-images/#circleci-base-image @@ -544,27 +516,6 @@ jobs: workflows: version: 2.1 - build_docs_only: - when: - and: - - <> - - not: <> - - not: <> - - not: <> - - not: <> - jobs: - - build_docs - - docs_linkcheck - - lint: - matrix: - parameters: - python_version: ["3.7", "3.8", "3.9", "3.10"] - - all_circleci_checks_succeeded: - requires: - - build_docs - - docs_linkcheck - - lint - build_code_and_docs: when: and: @@ -601,8 +552,6 @@ workflows: matrix: parameters: python_version: ["3.7", "3.8", "3.9", "3.10"] - - build_docs - - docs_linkcheck - all_circleci_checks_succeeded: requires: - e2e_tests @@ -612,8 +561,6 @@ workflows: - lint - pip_compile - win_pip_compile - - build_docs - - docs_linkcheck main_updated: when: diff --git a/.gitignore b/.gitignore index 67b5f964c1..8e06e36735 100644 --- a/.gitignore +++ b/.gitignore @@ -134,6 +134,11 @@ venv.bak/ /site /kedro/framework/html +# Sphinx documentation +# Additional files created by sphinx.ext.autosummary +# Some of them are actually tracked to control the output +/docs/source/kedro.* + # mypy .mypy_cache/ diff --git a/.readthedocs.yml b/.readthedocs.yml index 2f95ec4cf4..771a7351b9 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.7" + python: "3.8" nodejs: "19" apt_packages: - libasound2 @@ -17,12 +17,14 @@ build: post_create_environment: - npm install -g @mermaid-js/mermaid-cli - ./docs/kedro-datasets-docs.sh + pre_build: + - python -m sphinx -WETan -j auto -D language=en -b linkcheck -d _build/doctrees docs/source _build/linkcheck # Build documentation in the docs/ directory with Sphinx sphinx: builder: html - configuration: docs/conf.py - fail_on_warning: false # Turn back on soon + configuration: docs/source/conf.py + fail_on_warning: true # Build documentation with MkDocs # mkdocs: diff --git a/Makefile b/Makefile index 925c420681..d16bc18e78 100644 --- a/Makefile +++ b/Makefile @@ -44,9 +44,6 @@ linkcheck: pip install -e ".[docs]" ./docs/build-docs.sh "linkcheck" -devserver: build-docs - cd docs && npm install && npm start - package: clean install python setup.py sdist bdist_wheel diff --git a/docs/build-docs.sh b/docs/build-docs.sh index 19b1ca8d8d..5575b6b577 100755 --- a/docs/build-docs.sh +++ b/docs/build-docs.sh @@ -7,35 +7,12 @@ set -o nounset action=$1 -# Move some files around. We need a separate build directory, which would -# have all the files, build scripts would shuffle the files, -# we don't want that happening on the actual code locally. -# When running on ReadTheDocs, sphinx-build would run directly on the original files, -# but we don't care about the code state there. -rm -rf docs/build +# Reinstall kedro-datasets locally rm -rf kedro/datasets -mkdir docs/build/ -cp -r docs/_templates docs/conf.py docs/*.svg docs/*.json docs/build/ - bash docs/kedro-datasets-docs.sh if [ "$action" == "linkcheck" ]; then - sphinx-build -c docs/ -ETan -j auto -D language=en -b linkcheck docs/build/ docs/build/html + sphinx-build -WETan -j auto -D language=en -b linkcheck -d docs/build/doctrees docs/source docs/build/linkcheck elif [ "$action" == "docs" ]; then - sphinx-build -c docs/ -ETa -j auto -D language=en docs/build/ docs/build/html + sphinx-build -WETa -j auto -D language=en -b html -d docs/build/doctrees docs/source docs/build/html fi - -# Clean up build artefacts -rm -rf docs/build/html/_sources - -# Copy built HTML to temp directory, clean up build dir and replace with built docs only -rm -rf docs/temp -mkdir docs/temp/ -mkdir docs/temp/html -cp -rf docs/build/html/* docs/temp/html - -rm -rf docs/build -mkdir docs/build -mkdir docs/build/html -cp -rf docs/temp/html/* docs/build/html -rm -rf docs/temp diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index 839cab7e2d..0000000000 --- a/docs/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "kedro-docs", - "version": "1.0.0", - "main": "build/html/index.html", - "scripts": { - "serve": "browser-sync start --server 'build/html' --files 'build/html/_static/css/*.css'", - "watch": "copy-and-watch --watch source/css/*.css build/html/_static/css", - "start": "npm-run-all -p serve watch" - }, - "author": "Richard Westenra ", - "devDependencies": { - "browser-sync": "^2.26.7", - "copy-and-watch": "^0.1.2", - "npm-run-all": "^4.1.5" - } -} diff --git a/docs/source/css/qb1-sphinx-rtd.css b/docs/source/_static/css/qb1-sphinx-rtd.css similarity index 100% rename from docs/source/css/qb1-sphinx-rtd.css rename to docs/source/_static/css/qb1-sphinx-rtd.css diff --git a/docs/source/css/theme-overrides.css b/docs/source/_static/css/theme-overrides.css similarity index 100% rename from docs/source/css/theme-overrides.css rename to docs/source/_static/css/theme-overrides.css diff --git a/docs/_templates/autosummary/base.rst b/docs/source/_templates/autosummary/base.rst similarity index 100% rename from docs/_templates/autosummary/base.rst rename to docs/source/_templates/autosummary/base.rst diff --git a/docs/_templates/autosummary/class.rst b/docs/source/_templates/autosummary/class.rst similarity index 100% rename from docs/_templates/autosummary/class.rst rename to docs/source/_templates/autosummary/class.rst diff --git a/docs/_templates/autosummary/module.rst b/docs/source/_templates/autosummary/module.rst similarity index 100% rename from docs/_templates/autosummary/module.rst rename to docs/source/_templates/autosummary/module.rst diff --git a/docs/_templates/breadcrumbs.html b/docs/source/_templates/breadcrumbs.html similarity index 100% rename from docs/_templates/breadcrumbs.html rename to docs/source/_templates/breadcrumbs.html diff --git a/docs/_templates/layout.html b/docs/source/_templates/layout.html similarity index 100% rename from docs/_templates/layout.html rename to docs/source/_templates/layout.html diff --git a/docs/conf.py b/docs/source/conf.py similarity index 92% rename from docs/conf.py rename to docs/source/conf.py index 37707da7d9..f24953b35f 100644 --- a/docs/conf.py +++ b/docs/source/conf.py @@ -15,9 +15,7 @@ import importlib import os import re -import shutil import sys -from distutils.dir_util import copy_tree from inspect import getmembers, isclass, isfunction from pathlib import Path from typing import List, Tuple @@ -49,12 +47,8 @@ "sphinx.ext.napoleon", "sphinx_autodoc_typehints", "sphinx.ext.doctest", - "sphinx.ext.todo", - "sphinx.ext.coverage", - "sphinx.ext.mathjax", "sphinx.ext.ifconfig", "sphinx.ext.viewcode", - "nbsphinx", "sphinx_copybutton", "sphinxcontrib.mermaid", "myst_parser", @@ -68,6 +62,7 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] +html_static_path = ["_static"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: @@ -82,7 +77,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -305,23 +300,6 @@ # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False -# -- Extension configuration ------------------------------------------------- - -# nbsphinx_prolog = """ -# see here for prolog/epilog details: -# https://nbsphinx.readthedocs.io/en/0.3.1/prolog-and-epilog.html -# """ - -nbsphinx_epilog = """ -.. note:: - - Found a bug, or didn't find what you were looking for? 🙏 `Please file a - ticket `_ -""" - -# -- NBconvert kedro config ------------------------------------------------- -nbsphinx_kedro_name = "kedro" - # -- Kedro specific configuration ----------------------------------------- KEDRO_MODULES = [ "kedro.io", @@ -493,20 +471,6 @@ def autodoc_process_docstring(app, what, name, obj, options, lines): remove_arrows_in_examples(lines) -def _prepare_build_dir(app, config): - """Get current working directory to the state expected - by the ReadTheDocs builder. Shortly, it does the same as - ./build-docs.sh script except not running `sphinx-build` step.""" - build_root = Path(app.srcdir) - build_out = Path(app.outdir) - copy_tree(str(here / "source"), str(build_root)) - copy_tree(str(build_root / "api_docs"), str(build_root)) - shutil.rmtree(str(build_root / "api_docs")) - shutil.rmtree(str(build_out), ignore_errors=True) - copy_tree(str(build_root / "css"), str(build_out / "_static" / "css")) - shutil.rmtree(str(build_root / "css")) - - def env_override(default_appid): build_version = os.getenv("READTHEDOCS_VERSION") @@ -533,7 +497,6 @@ def _add_jinja_filters(app): def setup(app): - app.connect("config-inited", _prepare_build_dir) app.connect("builder-inited", _add_jinja_filters) app.connect("autodoc-process-docstring", autodoc_process_docstring) app.add_css_file("css/qb1-sphinx-rtd.css") @@ -573,4 +536,4 @@ def setup(app): # https://github.com/mermaidjs/mermaid.cli#linux-sandbox-issue mermaid_params = ["-p", here / "puppeteer-config.json", "-s", "2"] # https://github.com/kedro-org/kedro/issues/2451 -mermaid_version = mermaid_init_js = None +mermaid_version = mermaid_init_js = "" diff --git a/docs/source/contribution/development_for_databricks.md b/docs/source/contribution/development_for_databricks.md index da46975d7c..77987b382a 100644 --- a/docs/source/contribution/development_for_databricks.md +++ b/docs/source/contribution/development_for_databricks.md @@ -7,7 +7,7 @@ This guide describes how to efficiently develop features and fixes for Kedro on Databricks. Using this guide, you will be able to quickly test your locally modified version of Kedro on Databricks as part of a build-and-test development cycle. ```{note} -This page is for people developing changes to Kedro that need to test them on Databricks. If you are working on a Kedro project and need more information about project-deployment, consult the [documentation for deploying Kedro projects on Databricks](../deployment/databricks.md). +This page is for people developing changes to Kedro that need to test them on Databricks. If you are working on a Kedro project and need more information about workflows, consult the [documentation for developing a Kedro project on Databricks](../integrations/databricks_workspace.md). ``` ## Prerequisites diff --git a/docs/source/index.rst b/docs/source/index.rst index 391ec1edc0..7cf13db285 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -186,30 +186,11 @@ Welcome to Kedro's documentation! deployment/airflow_astronomer deployment/dask -.. toctree:: - :maxdepth: 2 - :caption: Databricks integration - - databricks_integration/visualisation - -.. toctree:: - :maxdepth: 2 - :caption: PySpark integration - - tools_integration/pyspark - -.. toctree:: - :maxdepth: 2 - :caption: FAQs - - faq/faq - faq/architecture_overview - faq/kedro_principles - .. toctree:: :maxdepth: 2 :caption: Resources + faq/faq resources/glossary diff --git a/docs/source/integrations/databricks.md b/docs/source/integrations/databricks.md index cc92f543fa..32523578a0 100644 --- a/docs/source/integrations/databricks.md +++ b/docs/source/integrations/databricks.md @@ -5,5 +5,5 @@ :maxdepth: 2 databricks_workspace.md -visualisation.md +databricks_visualisation.md ``` diff --git a/docs/source/integrations/pyspark.md b/docs/source/integrations/pyspark.md new file mode 100644 index 0000000000..19c3e4b39c --- /dev/null +++ b/docs/source/integrations/pyspark.md @@ -0,0 +1,8 @@ +# PySpark integration + +```{toctree} +:caption: PySpark +:maxdepth: 2 + +pyspark_integration.md +``` diff --git a/docs/source/integrations/pyspark.rst b/docs/source/integrations/pyspark.rst deleted file mode 100644 index b7c4cf97fe..0000000000 --- a/docs/source/integrations/pyspark.rst +++ /dev/null @@ -1,9 +0,0 @@ - -PySpark integration -============================================= - -.. toctree:: - :maxdepth: 2 - :caption: PySpark - - pyspark_integration.md diff --git a/docs/source/api_docs/kedro.config.rst b/docs/source/kedro.config.rst similarity index 100% rename from docs/source/api_docs/kedro.config.rst rename to docs/source/kedro.config.rst diff --git a/docs/source/api_docs/kedro.datasets.rst b/docs/source/kedro.datasets.rst similarity index 100% rename from docs/source/api_docs/kedro.datasets.rst rename to docs/source/kedro.datasets.rst diff --git a/docs/source/api_docs/kedro.extras.datasets.rst b/docs/source/kedro.extras.datasets.rst similarity index 100% rename from docs/source/api_docs/kedro.extras.datasets.rst rename to docs/source/kedro.extras.datasets.rst diff --git a/docs/source/api_docs/kedro.extras.logging.color_logger.ColorHandler.rst b/docs/source/kedro.extras.logging.color_logger.ColorHandler.rst similarity index 100% rename from docs/source/api_docs/kedro.extras.logging.color_logger.ColorHandler.rst rename to docs/source/kedro.extras.logging.color_logger.ColorHandler.rst diff --git a/docs/source/api_docs/kedro.framework.cli.cli.KedroCLI.rst b/docs/source/kedro.framework.cli.cli.KedroCLI.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.cli.cli.KedroCLI.rst rename to docs/source/kedro.framework.cli.cli.KedroCLI.rst diff --git a/docs/source/api_docs/kedro.framework.cli.hooks.manager.CLIHooksManager.rst b/docs/source/kedro.framework.cli.hooks.manager.CLIHooksManager.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.cli.hooks.manager.CLIHooksManager.rst rename to docs/source/kedro.framework.cli.hooks.manager.CLIHooksManager.rst diff --git a/docs/source/kedro.framework.cli.jupyter.JupyterCommandGroup.rst b/docs/source/kedro.framework.cli.jupyter.JupyterCommandGroup.rst new file mode 100644 index 0000000000..3562a7950f --- /dev/null +++ b/docs/source/kedro.framework.cli.jupyter.JupyterCommandGroup.rst @@ -0,0 +1,10 @@ +kedro.framework.cli.jupyter.JupyterCommandGroup +=============================================== + +.. currentmodule:: kedro.framework.cli.jupyter + +.. autoclass:: JupyterCommandGroup + :members: + +.. Removed all methods and properties, +.. see https://github.com/kedro-org/kedro/issues/2453 diff --git a/docs/source/api_docs/kedro.framework.cli.utils.CommandCollection.rst b/docs/source/kedro.framework.cli.utils.CommandCollection.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.cli.utils.CommandCollection.rst rename to docs/source/kedro.framework.cli.utils.CommandCollection.rst diff --git a/docs/source/api_docs/kedro.framework.cli.utils.rst b/docs/source/kedro.framework.cli.utils.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.cli.utils.rst rename to docs/source/kedro.framework.cli.utils.rst diff --git a/docs/source/api_docs/kedro.framework.context.rst b/docs/source/kedro.framework.context.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.context.rst rename to docs/source/kedro.framework.context.rst diff --git a/docs/source/api_docs/kedro.framework.session.shelvestore.ShelveStore.rst b/docs/source/kedro.framework.session.shelvestore.ShelveStore.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.session.shelvestore.ShelveStore.rst rename to docs/source/kedro.framework.session.shelvestore.ShelveStore.rst diff --git a/docs/source/api_docs/kedro.framework.session.store.BaseSessionStore.rst b/docs/source/kedro.framework.session.store.BaseSessionStore.rst similarity index 100% rename from docs/source/api_docs/kedro.framework.session.store.BaseSessionStore.rst rename to docs/source/kedro.framework.session.store.BaseSessionStore.rst diff --git a/docs/source/api_docs/kedro.io.rst b/docs/source/kedro.io.rst similarity index 100% rename from docs/source/api_docs/kedro.io.rst rename to docs/source/kedro.io.rst diff --git a/docs/source/api_docs/kedro.pipeline.rst b/docs/source/kedro.pipeline.rst similarity index 100% rename from docs/source/api_docs/kedro.pipeline.rst rename to docs/source/kedro.pipeline.rst diff --git a/docs/source/api_docs/kedro.runner.rst b/docs/source/kedro.runner.rst similarity index 100% rename from docs/source/api_docs/kedro.runner.rst rename to docs/source/kedro.runner.rst diff --git a/docs/kedro_logo.svg b/docs/source/kedro_logo.svg similarity index 100% rename from docs/kedro_logo.svg rename to docs/source/kedro_logo.svg diff --git a/docs/source/kedro_project_setup/starters.md b/docs/source/kedro_project_setup/starters.md index 0c12f3f349..4415d4f237 100644 --- a/docs/source/kedro_project_setup/starters.md +++ b/docs/source/kedro_project_setup/starters.md @@ -49,8 +49,8 @@ The Kedro team maintains the following starters for a range of Kedro projects: * [`astro-airflow-iris`](https://github.com/kedro-org/kedro-starters/tree/main/astro-airflow-iris): The [Kedro Iris dataset example project](../get_started/new_project.md) with a minimal setup for deploying the pipeline on Airflow with [Astronomer](https://www.astronomer.io/). * [`standalone-datacatalog`](https://github.com/kedro-org/kedro-starters/tree/main/standalone-datacatalog): A minimum setup to use the traditional [Iris dataset](https://www.kaggle.com/uciml/iris) with Kedro's [`DataCatalog`](../data/data_catalog.md), which is a core component of Kedro. This starter is of use in the exploratory phase of a project. For more information, read the guide to [standalone use of the `DataCatalog`](../notebooks_and_ipython/kedro_and_notebooks.md). This starter was formerly known as `mini-kedro`. * [`pandas-iris`](https://github.com/kedro-org/kedro-starters/tree/main/pandas-iris): The [Kedro Iris dataset example project](../get_started/new_project.md) -* [`pyspark-iris`](https://github.com/kedro-org/kedro-starters/tree/main/pyspark-iris): An alternative Kedro Iris dataset example, using [PySpark](../tools_integration/pyspark.md) -* [`pyspark`](https://github.com/kedro-org/kedro-starters/tree/main/pyspark): The configuration and initialisation code for a [Kedro pipeline using PySpark](../tools_integration/pyspark.md) +* [`pyspark-iris`](https://github.com/kedro-org/kedro-starters/tree/main/pyspark-iris): An alternative Kedro Iris dataset example, using [PySpark](../integrations/pyspark_integration.md) +* [`pyspark`](https://github.com/kedro-org/kedro-starters/tree/main/pyspark): The configuration and initialisation code for a [Kedro pipeline using PySpark](../integrations/pyspark_integration.md) * [`spaceflights`](https://github.com/kedro-org/kedro-starters/tree/main/spaceflights): The [spaceflights tutorial](../tutorial/spaceflights_tutorial.md) example code ## Starter versioning diff --git a/docs/source/nodes_and_pipelines/run_a_pipeline.md b/docs/source/nodes_and_pipelines/run_a_pipeline.md index ba861951dd..4d7fa7804c 100644 --- a/docs/source/nodes_and_pipelines/run_a_pipeline.md +++ b/docs/source/nodes_and_pipelines/run_a_pipeline.md @@ -46,7 +46,7 @@ kedro run --runner=ThreadRunner `SparkDataSet` doesn't work correctly with `ParallelRunner`. To add concurrency to the pipeline with `SparkDataSet`, you must use `ThreadRunner`. ``` -For more information on how to maximise concurrency when using Kedro with PySpark, please visit our guide on [how to build a Kedro pipeline with PySpark](../tools_integration/pyspark.md). +For more information on how to maximise concurrency when using Kedro with PySpark, please visit our guide on [how to build a Kedro pipeline with PySpark](../integrations/pyspark_integration.md). hook_manager: PluginManager = None, diff --git a/docs/puppeteer-config.json b/docs/source/puppeteer-config.json similarity index 100% rename from docs/puppeteer-config.json rename to docs/source/puppeteer-config.json diff --git a/docs/robots.txt b/docs/source/robots.txt similarity index 100% rename from docs/robots.txt rename to docs/source/robots.txt diff --git a/docs/source/tutorial/add_another_pipeline.md b/docs/source/tutorial/add_another_pipeline.md index 450b4dcf98..dfc7e5cf65 100644 --- a/docs/source/tutorial/add_another_pipeline.md +++ b/docs/source/tutorial/add_another_pipeline.md @@ -518,7 +518,7 @@ kedro run --runner=ThreadRunner kedro run --runner=module.path.to.my.runner ``` -`ParallelRunner` performs task parallelisation via multiprocessing, while `ThreadRunner` is intended for use with remote execution engines such as [Spark](../tools_integration/pyspark.md) and [Dask](/kedro.datasets.dask.ParquetDataSet). +`ParallelRunner` performs task parallelisation via multiprocessing, while `ThreadRunner` is intended for use with remote execution engines such as [Spark](../integrations/pyspark_integration.md) and [Dask](/kedro.datasets.dask.ParquetDataSet). You can find out more about the runners Kedro provides, and how to create your own, in the [pipeline documentation about runners](../nodes_and_pipelines/run_a_pipeline.md). atasets to work with different data formats (including CSV, Excel, and Parquet) diff --git a/docs/source/tutorial/package_a_project.md b/docs/source/tutorial/package_a_project.md index d86fc6a0bd..c91f23cf74 100644 --- a/docs/source/tutorial/package_a_project.md +++ b/docs/source/tutorial/package_a_project.md @@ -151,4 +151,4 @@ There are various methods to deploy packaged pipelines via Kedro plugins: * [Kedro-Docker](https://github.com/kedro-org/kedro-plugins/tree/main/kedro-docker) plugin for packaging and shipping Kedro projects within [Docker](https://www.docker.com/) containers. * [Kedro-Airflow](https://github.com/kedro-org/kedro-plugins/tree/main/kedro-airflow) to convert your Kedro project into an [Airflow](https://airflow.apache.org/) project. -* The [Deployment guide](../deployment/deployment_guide) touches on other deployment targets such as AWS Batch and Prefect, and there is a [range of third-party plugins for deployment](extend_kedro/plugins.md#community-developed-plugins). +* The [Deployment guide](../deployment/deployment_guide) touches on other deployment targets such as AWS Batch and Prefect, and there is a [range of third-party plugins for deployment](../extend_kedro/plugins.md#community-developed-plugins). diff --git a/kedro/config/common.py b/kedro/config/common.py index 4fb4d41b2f..48a3c90ce4 100644 --- a/kedro/config/common.py +++ b/kedro/config/common.py @@ -10,7 +10,7 @@ from yaml.parser import ParserError -from kedro.config import BadConfigException, MissingConfigException +from kedro.config.abstract_config import BadConfigException, MissingConfigException SUPPORTED_EXTENSIONS = [ ".yml", diff --git a/kedro/config/config.py b/kedro/config/config.py index 166f0636bf..557138f9ed 100644 --- a/kedro/config/config.py +++ b/kedro/config/config.py @@ -4,7 +4,7 @@ from pathlib import Path from typing import Any, Dict, Iterable, List -from kedro.config import AbstractConfigLoader +from kedro.config.abstract_config import AbstractConfigLoader from kedro.config.common import _get_config_from_patterns, _remove_duplicates diff --git a/kedro/config/omegaconf_config.py b/kedro/config/omegaconf_config.py index c3d0d02f27..ca1dbc2173 100644 --- a/kedro/config/omegaconf_config.py +++ b/kedro/config/omegaconf_config.py @@ -13,7 +13,7 @@ from yaml.parser import ParserError from yaml.scanner import ScannerError -from kedro.config import AbstractConfigLoader, MissingConfigException +from kedro.config.abstract_config import AbstractConfigLoader, MissingConfigException _config_logger = logging.getLogger(__name__) diff --git a/kedro/config/templated_config.py b/kedro/config/templated_config.py index 3468bf10dc..c6cec1bbf5 100644 --- a/kedro/config/templated_config.py +++ b/kedro/config/templated_config.py @@ -9,7 +9,7 @@ import jmespath -from kedro.config import AbstractConfigLoader +from kedro.config.abstract_config import AbstractConfigLoader from kedro.config.common import _get_config_from_patterns, _remove_duplicates IDENTIFIER_PATTERN = re.compile( diff --git a/kedro/io/__init__.py b/kedro/io/__init__.py index de6f6e49e4..1203d3ae19 100644 --- a/kedro/io/__init__.py +++ b/kedro/io/__init__.py @@ -1,6 +1,5 @@ """``kedro.io`` provides functionality to read and write to a -number of data sets. At core of the library is ``AbstractDataSet`` -which allows implementation of various ``AbstractDataSet``s. +number of data sets. At core of the library is the ``AbstractDataSet`` class. """ from .cached_dataset import CachedDataSet diff --git a/kedro/pipeline/modular_pipeline.py b/kedro/pipeline/modular_pipeline.py index 9309eed678..fa83e37c1d 100644 --- a/kedro/pipeline/modular_pipeline.py +++ b/kedro/pipeline/modular_pipeline.py @@ -157,7 +157,7 @@ def pipeline( tags: Union[str, Iterable[str]] = None, namespace: str = None, ) -> Pipeline: - """Create a ``Pipeline`` from a collection of nodes and/or ``Pipeline``s. + r"""Create a ``Pipeline`` from a collection of nodes and/or ``Pipeline``\s. Args: pipe: The nodes the ``Pipeline`` will be made of. If you diff --git a/setup.py b/setup.py index 22fd77c5c8..cd357428a8 100644 --- a/setup.py +++ b/setup.py @@ -109,17 +109,24 @@ def _collect_requirements(requires): "biosequence": _collect_requirements(biosequence_require), "dask": _collect_requirements(dask_require), "docs": [ + # docutils>=0.17 changed the HTML + # see https://github.com/readthedocs/sphinx_rtd_theme/issues/1115 "docutils==0.16", - "sphinx~=3.4.3", - "sphinx_rtd_theme==1.1.1", - "nbsphinx==0.8.1", - "nbstripout~=0.4", - "sphinx-autodoc-typehints==1.11.1", + "sphinx~=5.3.0", + "sphinx_rtd_theme==1.2.0", + # Regression on sphinx-autodoc-typehints 1.21 + # that creates some problematic docstrings + "sphinx-autodoc-typehints==1.20.2", "sphinx_copybutton==0.3.1", "ipykernel>=5.3, <7.0", "sphinxcontrib-mermaid~=0.7.1", - "myst-parser~=0.17.2", + "myst-parser~=1.0.0", "Jinja2<3.1.0", + # https://github.com/kedro-org/kedro-plugins/issues/141 + # https://github.com/kedro-org/kedro-plugins/issues/143 + "kedro-datasets[api,biosequence,dask,geopandas,matplotlib,holoviews,networkx,pandas,pillow,polars,video,plotly,redis,spark,svmlight,yaml]==1.1.1", + "kedro-datasets[tensorflow]==1.1.1; platform_system != 'Darwin' or platform_machine != 'arm64'", + "tensorflow-macos~=2.0; platform_system == 'Darwin' and platform_machine == 'arm64'", ], "geopandas": _collect_requirements(geopandas_require), "matplotlib": _collect_requirements(matplotlib_require), From e249d26d629d2b79fdc1297a23275519652495b4 Mon Sep 17 00:00:00 2001 From: Jannic <37243923+jmholzer@users.noreply.github.com> Date: Thu, 30 Mar 2023 18:00:15 +0100 Subject: [PATCH 3/6] Improve visibility of documentation for pipeline visualisation on Databricks (#2468) * Improve guide for launching Viz on Databricks Signed-off-by: Jannic Holzer * Add images Signed-off-by: Jannic Holzer * Add release note Signed-off-by: Jannic Holzer --------- Signed-off-by: Jannic Holzer --- RELEASE.md | 1 + .../integrations/databricks_visualisation.md | 16 +++++++++++++--- docs/source/meta/images/databricks_viz_demo.png | Bin 0 -> 95026 bytes docs/source/meta/images/databricks_viz_link.png | Bin 0 -> 15409 bytes 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 docs/source/meta/images/databricks_viz_demo.png create mode 100644 docs/source/meta/images/databricks_viz_link.png diff --git a/RELEASE.md b/RELEASE.md index 4dd780c048..48a9eb1090 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -15,6 +15,7 @@ ## Bug fixes and other changes * Improvements to documentation about configuration. +* Improvements to documentation on visualising Kedro projects on Databricks. ## Breaking changes to the API diff --git a/docs/source/integrations/databricks_visualisation.md b/docs/source/integrations/databricks_visualisation.md index e913f54ba0..69bef2dbad 100644 --- a/docs/source/integrations/databricks_visualisation.md +++ b/docs/source/integrations/databricks_visualisation.md @@ -1,12 +1,22 @@ -# How to run Kedro-Viz on Databricks +# Visualise a Kedro project in Databricks notebooks -[Kedro-Viz](../visualisation/kedro-viz_visualisation.md) is a tool that allows you to visualise your Kedro pipeline. It is a standalone web application that runs on a web browser, it can be run on a local machine or on Databricks itself. +[Kedro-Viz](../visualisation/kedro-viz_visualisation.md) is a tool that enables you to visualise your Kedro pipeline and metrics generated from your data science experiments. It is a standalone web application that runs on a web browser, it can be run on a local machine or in Databricks notebooks. For Kedro-Viz to run with your Kedro project, you need to ensure that both the packages are installed in the same scope (notebook-scoped vs. cluster library). This means that if you `%pip install kedro` from inside your notebook then you should also `%pip install kedro-viz` from inside your notebook. If your cluster comes with Kedro installed on it as a library already then you should also add Kedro-Viz as a [cluster library](https://docs.microsoft.com/en-us/azure/databricks/libraries/cluster-libraries). +To run Kedro-Viz on Databricks you must first [launch the Kedro IPython extension](./databricks_workspace.md#9-using-the-kedro-ipython-extension). + Kedro-Viz can then be launched in a new browser tab with the `%run_viz` line magic: ```ipython -In [2]: %run_viz +%run_viz ``` + +This command presents you with a link to the Kedro-Viz web application. + +![databricks_viz_link](../meta/images/databricks_viz_link.png) + +Clicking this link opens a new browser tab running Kedro-Viz for your project. + +![databricks_viz_demo](../meta/images/databricks_viz_demo.png) diff --git a/docs/source/meta/images/databricks_viz_demo.png b/docs/source/meta/images/databricks_viz_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..d4388e412ac5ab6747dcaf26a5d97337d6837c5a GIT binary patch literal 95026 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 literal 0 HcmV?d00001 diff --git a/docs/source/meta/images/databricks_viz_link.png b/docs/source/meta/images/databricks_viz_link.png new file mode 100644 index 0000000000000000000000000000000000000000..71a8fc94553213dc4bc25d1e71e78b1bb4d77642 GIT binary patch literal 15409 zcmeIZbzD_j*ES4D3DO`4(%mK95&}xsM!LJZTN+eadehzA4VzZ!lC@9`UC@5Up zltu-9;DWUgNXl4728s?iMudWa#)NtT965BH?6WVPYW@L?R&};kP$5=2aAv_)l}-F99-BM@L&;W@Z-`7bX{WCL4Pb zW>y{^9%dFcW;QlP;0{IyH)}^dS4L|G^1nOzpMJ!Q91QHuY#q&PtVtgG)zi0eaugsV zdmQM0fBt?>BUiKkj%4ldpJ@RTWPZHD%*w>V{BO-1&5Zv)nmu0myV+m!`g=J3$If^~ zZ7gldtMYsOdpy9<{F z3y)FjHV^L2y#>L(!z<4bx4g5`A2+Rs?|0Qlt0qV0FfqdWA2`PuHz~+SV1EC6l!9?{ zb7OLEThH+IN#?Stl}YBD>5U`+`ohFOhyMN3PvLia>$zH%k#yt_W* zblOql^t`mKTL+Q-F$M`t5`}!`YdDLq*`ZFm&S4zZ^WEGMcEcJ?&inDSO1aa+TuY_| zoR+q3colHlB4PK8JmnxnS7N&+TtjpAd3L|D}xvhUrvk3$PRu zV{+<3wCQlM&4Y)knNF|&cr0O9ws%m2bQYAE>10=?MgO*D)041ca#!2mZ>>@>a+v>R zG!d8s7v%tI%>A3C_u^e~A-;&ee}oHRPfkw2Z3$oY(yAE>FOhAKDV;j};RYa?yT416 z1cv7wl-Ac#5t;bmYU~NC%xo%p-_r0uI*mnzDcFfMYq*b(0@Ek_(u;g8B7;WlP&|XW zKD}D0BYjrx?93=7QoWaIzI;caYKb|A`S%Dm<^JZRcNo^#$BYibILe-u%%K| zt<_wky@DVlsc_zXw}jJjn#Dw2_ACwj!QLn!K#w@Ru7AdM(d*j7C@ROWDj(<(#EmrB{HV}_Wek-J zTdj!O{ne(`ScXW4QjRsT5y7sPJf7I)N;tEBUS%z_IEO`k+{a($kSzff1Wm~_C%u!G z?rm-{SuDjELx~QdFRDONtjy=KoYpnyi>mRyyM7U7QM<9XQpxYQCBNC2!VrC2+7<8C z8%m-2R2I87yHpQ_h(*^|;G~~iVen|BCw#vHfw-Df^aJ-KWt?i^v1ycfVK%nxFM3-k z3`IW~hC^R09{!v*?|jkYaHa=W=Os$p!~M^IfA(EzvOtNNfXh0?1C8fu!DUJP=6rv3KB+-TQJK9@ zmGu|>7M_I#E#R&*YMD(ICsl

a@xD=qVM9H>OtLn*p`xks!Xn8)Uu` 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 XbXUb>r13nyGb<%7D^~hi*Z= Date: Fri, 31 Mar 2023 17:09:07 +0100 Subject: [PATCH 4/6] Jupyter e2e test (#2446) * Update sh_run.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * add polling Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update windows_reqs.txt Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * try without util.wait.for Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * add wait after jupyter notebook execution Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * revert Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update jupyter.feature Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * wait 2 minutes Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * fix keyword Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * fix timeouts Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * test Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * add readline from stderr Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * revert back to terminate() Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * debug Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * lint Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * shell=True Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * redirect stderr to stdout Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * add raise timeout Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * Update cli_steps.py Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> * release notes Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> --------- Signed-off-by: SajidAlamQB <90610031+SajidAlamQB@users.noreply.github.com> --- RELEASE.md | 1 + features/jupyter.feature | 2 ++ features/steps/cli_steps.py | 33 +++++++++++++++------------------ features/steps/sh_run.py | 4 +++- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 48a9eb1090..3dd1c97e62 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -15,6 +15,7 @@ ## Bug fixes and other changes * Improvements to documentation about configuration. +* Improvements to Jupyter E2E tests. * Improvements to documentation on visualising Kedro projects on Databricks. ## Breaking changes to the API diff --git a/features/jupyter.feature b/features/jupyter.feature index e4f5b50dba..188d07f2f4 100644 --- a/features/jupyter.feature +++ b/features/jupyter.feature @@ -10,10 +10,12 @@ Feature: Jupyter targets in new project Scenario: Execute jupyter notebook target When I execute the kedro jupyter command "notebook --no-browser" + Then I wait for the jupyter webserver to run for up to "120" seconds Then jupyter notebook should run on port 8888 Scenario: Execute jupyter lab target When I execute the kedro jupyter command "lab --no-browser" + Then I wait for the jupyter webserver to run for up to "120" seconds Then Jupyter Lab should run on port 8888 Scenario: Execute node convert into Python files diff --git a/features/steps/cli_steps.py b/features/steps/cli_steps.py index 04f7d2d5e7..76bb0d2722 100644 --- a/features/steps/cli_steps.py +++ b/features/steps/cli_steps.py @@ -128,7 +128,6 @@ def _check_service_up(context: behave.runner.Context, url: str, string: str): """ response = requests.get(url, timeout=1.0) response.raise_for_status() - data = response.text assert string in data assert context.result.poll() is None @@ -337,10 +336,22 @@ def exec_notebook(context, command): # Jupyter notebook forks a child process from a parent process, and # only kills the parent process when it is terminated context.result = ChildTerminatingPopen( - cmd, env=context.env, cwd=str(context.root_project_dir) + cmd, env=context.env, cwd=str(context.root_project_dir), universal_newlines=True ) +@then('I wait for the jupyter webserver to run for up to "{timeout:d}" seconds') +def wait_for_notebook_to_run(context, timeout): + timeout_start = time() + while time() < timeout_start + timeout: + stdout = context.result.stdout.readline() + if "http://127.0.0.1:" in stdout: + break + + if time() >= timeout_start + timeout: + raise TimeoutError("Failed to run Jupyter server in time") + + @when("Wait until the process is finished") def wait(context): """Wait for child process to terminate.""" @@ -565,14 +576,7 @@ def check_jupyter_nb_proc_on_port(context: behave.runner.Context, port: int): """ url = f"http://localhost:{port}" try: - util.wait_for( - func=_check_service_up, - context=context, - url=url, - string="Jupyter Notebook", - timeout_=15, - print_error=True, - ) + _check_service_up(context, url, "Jupyter Notebook") finally: context.result.terminate() @@ -588,14 +592,7 @@ def check_jupyter_lab_proc_on_port(context: behave.runner.Context, port: int): """ url = f"http://localhost:{port}" try: - util.wait_for( - func=_check_service_up, - timeout_=20, - context=context, - url=url, - string=' None: **kwargs: keyword arguments such as env and cwd """ - super().__init__(cmd, **kwargs) # type: ignore + super().__init__( # type: ignore + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs + ) def terminate(self) -> None: """Terminate process and children.""" From 0497d45b4ddb8ba53118ced0e855cbb088d7323e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Cano=20Rodr=C3=ADguez?= Date: Mon, 3 Apr 2023 12:14:47 +0200 Subject: [PATCH 5/6] Add 404 page (#2486) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add 404 page Fix gh-2464. Signed-off-by: Juan Luis Cano Rodríguez * Fix broken link Signed-off-by: Juan Luis Cano Rodríguez --------- Signed-off-by: Juan Luis Cano Rodríguez --- docs/source/conf.py | 1 + docs/source/deployment/aws_batch.md | 2 +- setup.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f24953b35f..a857f9ad18 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -52,6 +52,7 @@ "sphinx_copybutton", "sphinxcontrib.mermaid", "myst_parser", + "notfound.extension", ] # enable autosummary plugin (table of contents for modules/classes/class diff --git a/docs/source/deployment/aws_batch.md b/docs/source/deployment/aws_batch.md index 383ce79f6e..ccb79b8624 100644 --- a/docs/source/deployment/aws_batch.md +++ b/docs/source/deployment/aws_batch.md @@ -105,7 +105,7 @@ A job queue is the bridge between the submitted jobs and the compute environment ### Configure the credentials -Ensure you have the necessary AWS credentials in place before moving on, so that your pipeline can access and interact with the AWS services. Check out [the AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config) for instructions on how to set this up. +Ensure you have the necessary AWS credentials in place before moving on, so that your pipeline can access and interact with the AWS services. Check out [the AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) for instructions on how to set this up. ```{note} You should configure the default region to match the region where you've created the Batch resources. diff --git a/setup.py b/setup.py index cd357428a8..00857640ad 100644 --- a/setup.py +++ b/setup.py @@ -118,6 +118,7 @@ def _collect_requirements(requires): # that creates some problematic docstrings "sphinx-autodoc-typehints==1.20.2", "sphinx_copybutton==0.3.1", + "sphinx-notfound-page", "ipykernel>=5.3, <7.0", "sphinxcontrib-mermaid~=0.7.1", "myst-parser~=1.0.0", From ebfed0c49a85f7157151d881654fd0378bacfb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Cano=20Rodr=C3=ADguez?= Date: Mon, 3 Apr 2023 13:23:55 +0200 Subject: [PATCH 6/6] Migrate most project metadata to static `pyproject.toml` (#2475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove deprecated tests_require Signed-off-by: Juan Luis Cano Rodríguez * Migrate most project metadata to static pyproject.toml See gh-2152. Signed-off-by: Juan Luis Cano Rodríguez * Replace direct setup.py invokations by standard command Signed-off-by: Juan Luis Cano Rodríguez --------- Signed-off-by: Juan Luis Cano Rodríguez --- Makefile | 4 ++-- pyproject.toml | 44 ++++++++++++++++++++++++++++++++++++++++++++ setup.py | 44 +------------------------------------------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index d16bc18e78..e680e12620 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ linkcheck: ./docs/build-docs.sh "linkcheck" package: clean install - python setup.py sdist bdist_wheel + python -m pip install build && python -m build install-test-requirements: pip install -r test_requirements.txt @@ -60,7 +60,7 @@ print-python-env: @./tools/print_env.sh databricks-build: - python setup.py bdist_wheel + python -m pip install build && python -m build python ./tools/databricks_build.py sign-off: diff --git a/pyproject.toml b/pyproject.toml index 7971446d5f..ba356a7e7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,50 @@ # Minimum requirements for the build system to execute. requires = ["setuptools>=65.5.1", "wheel"] # PEP 518 specifications. +[project] +name = "kedro" +authors = [ + {name = "Kedro"} +] +description = "Kedro helps you build production-ready data and analytics pipelines" +requires-python = ">=3.7, <3.11" +keywords = [ + "pipelines", + "machine learning", + "data pipelines", + "data science", + "data engineering", +] +license = {text = "Apache Software License (Apache 2.0)"} +classifiers = [ + "Development Status :: 4 - Beta", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", +] +dynamic = ["readme", "version", "dependencies", "optional-dependencies"] + +[project.urls] +Homepage = "https://kedro.org" +Source = "https://github.com/kedro-org/kedro" +Documentation = "https://docs.kedro.org" +Tracker = "https://github.com/kedro-org/kedro/issues" + +[project.scripts] +kedro = "kedro.framework.cli:main" + +[tool.setuptools] +zip-safe = false + +[tool.setuptools.packages.find] +include = ["kedro*"] + +[tool.setuptools.dynamic] +readme = {file = "README.md", content-type = "text/markdown"} +version = {attr = "kedro.__version__"} +dependencies = {file = "dependency/requirements.txt"} + [tool.black] exclude = "/templates/|^features/steps/test_starter" diff --git a/setup.py b/setup.py index 00857640ad..274ffa2a3a 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,9 @@ -import re from codecs import open from glob import glob from itertools import chain from os import path -from setuptools import find_packages, setup +from setuptools import setup name = "kedro" here = path.abspath(path.dirname(__file__)) @@ -15,28 +14,10 @@ HDFS = "hdfs>=2.5.8, <3.0" S3FS = "s3fs>=0.3.0, <0.5" -# get package version -with open(path.join(here, name, "__init__.py"), encoding="utf-8") as f: - result = re.search(r'__version__ = ["\']([^"\']+)', f.read()) - - if not result: - raise ValueError("Can't find the version in kedro/__init__.py") - - version = result.group(1) - # get the dependencies and installs with open("dependency/requirements.txt", encoding="utf-8") as f: requires = [x.strip() for x in f if x.strip()] -# get test dependencies and installs -with open("test_requirements.txt", encoding="utf-8") as f: - test_requires = [x.strip() for x in f if x.strip() and not x.startswith("-r")] - - -# Get the long description from the README file -with open(path.join(here, "README.md"), encoding="utf-8") as f: - readme = f.read() - template_files = [] for pattern in ["**/*", "**/.*", "**/.*/**", "**/.*/.**"]: template_files.extend( @@ -164,31 +145,8 @@ def _collect_requirements(requires): extras_require["all"] = _collect_requirements(extras_require) setup( - name=name, - version=version, - description="Kedro helps you build production-ready data and analytics pipelines", - license="Apache Software License (Apache 2.0)", - long_description=readme, - long_description_content_type="text/markdown", - url="https://github.com/kedro-org/kedro", - python_requires=">=3.7, <3.11", - packages=find_packages(exclude=["docs*", "tests*", "tools*", "features*"]), - include_package_data=True, - tests_require=test_requires, - install_requires=requires, - author="Kedro", - entry_points={"console_scripts": ["kedro = kedro.framework.cli:main"]}, package_data={ name: ["py.typed", "test_requirements.txt"] + template_files }, - zip_safe=False, - keywords="pipelines, machine learning, data pipelines, data science, data engineering", - classifiers=[ - "Development Status :: 4 - Beta", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - ], extras_require=extras_require, )