From c6a1f30e5686a1512b3888fb1b9f004c50d65b20 Mon Sep 17 00:00:00 2001 From: Jannic <37243923+jmholzer@users.noreply.github.com> Date: Thu, 1 Jun 2023 15:11:08 +0100 Subject: [PATCH] Create a databricks-iris starter that enables packaged deployment on Databricks (#129) * Move all downstream datasets to FileStore Signed-off-by: Jannic Holzer * Add databricks-specific logging settings Signed-off-by: Jannic Holzer * Move databricks_run.py Signed-off-by: Jannic Holzer * Modify databricks logging path Signed-off-by: Jannic Holzer * Lint Signed-off-by: Jannic Holzer * Lint Signed-off-by: Jannic Holzer * Revert all Databricks-related changes to pyspark-iris Signed-off-by: Jannic Holzer * Add databricks-iris starter Signed-off-by: Jannic Holzer * Update readme Signed-off-by: Jannic Holzer * Update databricks-iris/{{ cookiecutter.repo_name }}/conf/base/logging.yml Co-authored-by: Nok Lam Chan * Remove __main__.py Signed-off-by: Jannic Holzer * Fix links Signed-off-by: Jannic Holzer --------- Signed-off-by: Jannic Holzer Co-authored-by: Nok Lam Chan --- databricks-iris/.gitignore | 155 ++++++++++++ databricks-iris/README.md | 59 +++++ databricks-iris/cookiecutter.json | 6 + databricks-iris/credentials.yml | 18 ++ databricks-iris/images/iris_pipeline.png | Bin 0 -> 130652 bytes databricks-iris/prompts.yml | 9 + .../{{ cookiecutter.repo_name }}/.gitignore | 152 ++++++++++++ .../{{ cookiecutter.repo_name }}/README.md | 122 ++++++++++ .../conf/README.md | 26 ++ .../conf/base}/catalog.yml | 16 +- .../conf/base/logging.yml | 32 +++ .../conf/base/parameters.yml | 3 + .../conf/base/spark.yml | 8 + .../conf/local/.gitkeep | 0 .../data/01_raw/.gitkeep | 0 .../data/01_raw/iris.csv | 151 ++++++++++++ .../data/02_intermediate/.gitkeep | 0 .../data/03_primary/.gitkeep | 0 .../data/04_feature/.gitkeep | 0 .../data/05_model_input/.gitkeep | 0 .../data/06_models/.gitkeep | 0 .../data/07_model_output/.gitkeep | 0 .../data/08_reporting/.gitkeep | 0 .../docs/source/conf.py | 224 ++++++++++++++++++ .../docs/source/index.rst | 19 ++ .../notebooks/.gitkeep | 0 .../pyproject.toml | 17 ++ .../{{ cookiecutter.repo_name }}/setup.cfg | 3 + .../src/requirements.txt | 16 ++ .../{{ cookiecutter.repo_name }}/src/setup.py | 39 +++ .../src/tests/__init__.py | 0 .../src/tests/test_pipeline.py | 9 + .../src/tests/test_run.py | 39 +++ .../README.md | 72 ++++++ .../__init__.py | 4 + .../databricks_run.py | 29 +++ .../hooks.py | 24 ++ .../nodes.py | 73 ++++++ .../pipeline.py | 38 +++ .../pipeline_registry.py | 16 ++ .../settings.py | 38 +++ 41 files changed, 1409 insertions(+), 8 deletions(-) create mode 100644 databricks-iris/.gitignore create mode 100644 databricks-iris/README.md create mode 100644 databricks-iris/cookiecutter.json create mode 100644 databricks-iris/credentials.yml create mode 100644 databricks-iris/images/iris_pipeline.png create mode 100644 databricks-iris/prompts.yml create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/.gitignore create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/README.md create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/conf/README.md rename {pyspark-iris/{{ cookiecutter.repo_name }}/conf/databricks => databricks-iris/{{ cookiecutter.repo_name }}/conf/base}/catalog.yml (79%) create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/conf/base/logging.yml create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/conf/base/parameters.yml create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/conf/base/spark.yml create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/conf/local/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/iris.csv create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/02_intermediate/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/03_primary/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/04_feature/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/05_model_input/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/06_models/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/07_model_output/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/data/08_reporting/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/docs/source/conf.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/docs/source/index.rst create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/notebooks/.gitkeep create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/pyproject.toml create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/setup.cfg create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/requirements.txt create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/setup.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/tests/__init__.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_pipeline.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_run.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/README.md create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/__init__.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/databricks_run.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/hooks.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/nodes.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline_registry.py create mode 100644 databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/settings.py diff --git a/databricks-iris/.gitignore b/databricks-iris/.gitignore new file mode 100644 index 00000000..89ff27bd --- /dev/null +++ b/databricks-iris/.gitignore @@ -0,0 +1,155 @@ +########################## +# KEDRO PROJECT + +# ignore all local configuration +conf/local/** +!conf/local/.gitkeep +.telemetry + +# ignore potentially sensitive credentials files +conf/**/*credentials* + +# ignore everything in the following folders +data/** +logs/** + +# except their sub-folders +!data/**/ +!logs/**/ + +# also keep all .gitkeep files +!.gitkeep + +# also keep the example dataset +!data/01_raw/iris.csv + + +########################## +# Common files + +# IntelliJ +.idea/ +*.iml +out/ +.idea_modules/ + +### macOS +*.DS_Store +.AppleDouble +.LSOverride +.Trashes + +# Vim +*~ +.*.swo +.*.swp + +# emacs +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc + +# JIRA plugin +atlassian-ide-plugin.xml + +# C extensions +*.so + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/databricks-iris/README.md b/databricks-iris/README.md new file mode 100644 index 00000000..caaa2e81 --- /dev/null +++ b/databricks-iris/README.md @@ -0,0 +1,59 @@ +# The `databricks-iris` Kedro starter + +## Introduction + +The code in this repository demonstrates best practice when working with Kedro and PySpark on Databricks. It contains a Kedro starter template with some initial configuration and an example pipeline, it accompanies the documentation on [developing and deploying Kedro projects on Databricks](https://docs.kedro.org/en/stable/integrations/index.html#databricks-integration). + +This repository is a fork of the `pyspark-iris` starter that has been modified to run natively on Databricks. + +## Getting started + +The starter template can be used to start a new project using the [`starter` option](https://docs.kedro.org/en/stable/kedro_project_setup/starters.html) in `kedro new`: + +```bash +kedro new --starter=databricks-iris +``` + +## Features + +### Configuration for Databricks in `conf/base` + +This starter has a base configuration that allows it to run natively on Databricks. Directories to store data and logs still need to be manually created in the user's Databricks DBFS instance: + +```bash +/dbfs/FileStore/iris-databricks/data +/dbfs/FileStore/iris-databricks/logs +``` + +See the documentation on deploying a packaged Kedro project to Databricks for more information. + +### Databricks entry point + +The starter contains a script and an entry point (`databricks_run.py`) that enables a packaged project created with this starter to run on Databricks. See the documentation on deploying a packaged Kedro project to Databricks for more information. + +### Single configuration in `/conf/base/spark.yml` + +While Spark allows you to specify many different [configuration options](https://spark.apache.org/docs/latest/configuration.html), this starter uses `/conf/base/spark.yml` as a single configuration location. + +### `SparkSession` initialisation + +This Kedro starter contains the initialisation code for `SparkSession` in the `ProjectContext` and takes its configuration from `/conf/base/spark.yml`. Modify this code if you want to further customise your `SparkSession`, e.g. to use [YARN](https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html). + +### Configures `MemoryDataSet` to work with Spark objects + +Out of the box, Kedro's `MemoryDataSet` works with Spark's `DataFrame`. However, it doesn't work with other Spark objects such as machine learning models unless you add further configuration. This Kedro starter demonstrates how to configure `MemoryDataSet` for Spark's machine learning model in the `catalog.yml`. + +> Note: The use of `MemoryDataSet` is encouraged to propagate Spark's `DataFrame` between nodes in the pipeline. A best practice is to delay triggering Spark actions for as long as needed to take advantage of Spark's lazy evaluation. + +### An example machine learning pipeline that uses only `PySpark` and `Kedro` + +![Iris Pipeline Visualisation](./images/iris_pipeline.png) + +This Kedro starter uses the simple and familiar [Iris dataset](https://www.kaggle.com/uciml/iris). It contains the code for an example machine learning pipeline that runs a 1-nearest neighbour classifier to classify an iris. +[Transcoding](https://kedro.readthedocs.io/en/stable/data/data_catalog.html#transcoding-datasets) is used to convert the Spark Dataframes into pandas DataFrames after splitting the data into training and testing sets. + +The pipeline includes: + +* A node to split the data into training dataset and testing dataset using a configurable ratio +* A node to run a simple 1-nearest neighbour classifier and make predictions +* A node to report the accuracy of the predictions performed by the model diff --git a/databricks-iris/cookiecutter.json b/databricks-iris/cookiecutter.json new file mode 100644 index 00000000..910abee6 --- /dev/null +++ b/databricks-iris/cookiecutter.json @@ -0,0 +1,6 @@ +{ + "project_name": "Iris", + "repo_name": "{{ cookiecutter.project_name.strip().replace(' ', '-').replace('_', '-').lower() }}", + "python_package": "{{ cookiecutter.project_name.strip().replace(' ', '_').replace('-', '_').lower() }}", + "kedro_version": "{{ cookiecutter.kedro_version }}" +} diff --git a/databricks-iris/credentials.yml b/databricks-iris/credentials.yml new file mode 100644 index 00000000..3cbffcd7 --- /dev/null +++ b/databricks-iris/credentials.yml @@ -0,0 +1,18 @@ +# Here you can define credentials for different data sets and environment. +# +# THIS FILE MUST BE PLACED IN `conf/local`. DO NOT PUSH THIS FILE TO GitHub. +# +# Example: +# +# dev_s3: +# client_kwargs: +# aws_access_key_id: token +# aws_secret_access_key: key +# +# prod_s3: +# aws_access_key_id: token +# aws_secret_access_key: key +# +# dev_sql: +# username: admin +# password: admin diff --git a/databricks-iris/images/iris_pipeline.png b/databricks-iris/images/iris_pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..65e832cf871818e83ea2a5d7d864991ba9010f67 GIT binary patch literal 130652 zcmeFZby$>J+c*jcA|irf=Eg;q=3>P9Re!dHFR5mC@n~%64ISRihxMxP%}d} z4Bazxo&oo__kMrhxvq2mIscp&FNcTqthm=*>t1(EsJf~g*=4%RczAeZ3i7fVcz72! z@$fD(U%CjisQj9X#KXH{V=W`2t{@`=Qg?B*u(mVD!;=sFq)V))*+HFZsG(pLq@M8x zK^SG6@uu(2CHWh6Z&BXJ@|R#|B|g+ZYz9ShRrUJ(y%WHgDyTwOV=5MmT7s$U$^}3WZJ0mQjB!l>a-= z~H>sXF%Y+T*5)Y(*HB5`{VmBSjjdo&6|EDcDZ&*rbVm9l>1F|2BCmj1ivJ+u>eiB zqU-F?esv~~kaSMfn^76#$n?}O*2R|AoSAmM%p>Q}T;Z)Bc8FiX+G2+;6lB66s^UO` z$}2o1W*3~5ER9&}G(Wz%zz`Y40V3?N>2CTEi@8Qp#}X*L$to)iVoatPkbFQ$q>eRL z&#MK$?!xrH!qAFL(f;%TU7q{l^BBv~kzQrCNoDgByV>*lBl&FiTNM!uYVX3hBc0%o zY@Wb-{0NQ$e5IE+AI9EPxWWpaYV!nbM98(+^4K|4lW&MdwhQ_E;FD&bemH&c%SR{6 zuhsJVGO^#JZq1SF!tTtT7)(`04pNdgUjT`kwIx(PbZQe%XB1>06!($ll%uaIeUQ&s zjg4#eP?NEjbIwesx}eC@ifKdL7yNY18Ok>Etu`B%ZpztyWP{RTswb(vP}L72Vyd zfq0KhOiX5ljQA&4gQ=U=v1>^^8#jGbZsIu=#ui21_ztPwmJW0z;jA9~Fjducd9=lM zGLUAIxEXZi17Qj1TE;699`9?<7I}Gyy6{{dJ-koU*-Tf=V0Uq%iL03AHlADhwPZZY zrpHc1lXwSHE7ru^k7zu}y{{26F+tu0-DFw_A)9$q%_JcYy8ce~?w0(6=x{Tp>#{*z zQVUF(zZA{HOK;>z`#%Z?u}1F5v%3&`y@7xnBh~J|8&DS?qN;ct{6*sat&h@_{aaSl zU|LSu#cxXeF6GzZuSdSJ_Ju8xm6Q2}x|`w+Hhum~wD95R`E3qrr54_Yw1TAU&A*Ek z^Do*4_8!rVymNcW=zOQANxz!!S#y-<^`3Ut*|N=hhu*$4#$jncil!qrxlY-GRC$<$ zubp0c_T#2B^^412KC3?&eI%?bOm?6lIxQY0Z+3k>1mVP;b-gTfFjOhzR_IBH%1@mc z%9lc+vb=Xhq6p+mm>Jm8w3H3x#$~{&wTd>ZdyxXa7R-cPghf7bFwsPH{(^S2|I+Q~ z?Wm`+e^1sLab4+}de+mpr4u0pTq-=2| zsPsw5KIggv{ktBg6ulI&lzU*PThD4;-@WDWm3PaRA&aXHgW@?SZ-O4?-@JV>?O{Yo zigRLrq1;f};OvU|>Zg_UVcY)I0od?CpV~-TuF01Gt;Ua`5A744S#Y`1?%?gP?8F4+ z;7>?d6_2L3P31Ndw=lhHeka{>y~XdH&=pDAk`F&VxO~vLIZP|g)Ao`6quedEhX^y@ z@oLu)1O=Aql~ymk+`b)}T2B&1wj&#uC%WT~ROOu3Y!bkg#u>AlUo z=_l)o@!YZ8&hbg_*u5*OHmguUs#}b=qPh)|$^;qh*6lRyXvRmz8jAVKXUA`hYfr$d zvL}eg)GCY08#kmNo6f(SN0*#huet3)s6=#xjoqbF>XLt|-byhDzW(m`>ZdCOx4k

yT$vxZ&SNdP3r3E&5Q+%=@BD{WyGyI$D^gA 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

irn(D)8 zF@mpLP|uU0p<(n(`83fiXLS5_$iRX#`f7<9`TrTq{h!uCvDcv3^eY?1Zx9Lm)$jT> zv1T=hWBQ?rQ&@cNHLcxGR{4#_;mqgBhobocwY3>Ck86m;=7cb3jsw)-ibu;-7u_?) z=zku5!!CyFxxF3+^1PRo#ee@i5d&Td5-mscKdp+O#1PznQk@E9{@=-_M5s<#F?!`E zf7kSTb-r@|dt)`>Ghh0PzdsHzIR=PZXrFi8Ao}McE+3#q@xQi|NB~k`l!N)_4LT{{r(>g7Oa6bBPeTZbhrY-@d}wAq0DbEN--LV_Busm{;ehAPpOq5ggGJho(q>^-i#2Az zEG>h<@D7;t0nxTxT7GG(*I^gn`Aoe2cj*CO>3nP9N*G!`q(?q#)Du$8jF6s~(MkSQ z0SVmtk1bb!i+~1rSpsQErC>eW>W-pe2-U_U-66Is?PsGtd)Q~!aJS>Y5tGp$2MRWv zt(t$fi`oFlkvwCu1)C1F!8@v2pzik<1crNmbgZIhlcWy6asqDoN5EpPs31}~Hi|9{ zQsaL0WNIq!;szrFBkb$fCt|YVmEd!6eOupnI<1cF=YwjY`o^=b%uZ=VZ9#?Ge>uZC zQ8&5%zHUMg2b_gP`3n<15ru7$Sh8jCFzfcPEcXVh2(V+cD2wEs0crIu{iZlh!Op_H5K-nm(e$FP7)K>Q@#Ev0QdVN`c_m) zY`aF5oG)=_4lXopEvWb2Tt#zxbl+M8>$=v2>-Oq2#ugh9YGxx)H0&JIMy*FHVLoey zy-OiIx&ot6m!w8QVl8zFc#6&K8jf0WT$qiMUBW;AZZs7$1=ZUUniV%#m>~Vq8|}By zsiMqjQ?U(I^ul!*5Uu+URAeQJ&SriLy>L2|P|Taxo<4ZU^Y_c9z}EdJ)|DZ<;_JD5 z%hfoYKnBK^rt-lD?RWS+y`|w8oe6nf(ANT!u|``mD9332lJ8Qt z0&x))dwxI=psC>sX|J5UU|xXuvRv!L+a<1Mw_%m4k{@NXv$-&G0 zed2Q^WfmPnh?L2`S6mUdz9YJ2ov0JcRnhTcUz^ zV3@@2ft`7BpF#qBnwwjVjK)IYlPfmT+kxQJo0GC}_#$`Wq}M`RoDx+J4Hy;P<$R9% zJA;?=KDdo}p>sE+c>^MeIa0J`Pj4YKfcU14@rI6?WJKEKxUV3#U}|a=v9mLKT!zF? zOr?$vsK1P)L2!U#x1AYBpS=44iiQ_VJ@t!N4CHN9G~_5jyi?J z=7vqz*mXX^zs{oB6C*n#;CSj=1<+hlG!xv@G=!?G_!VEhYf-T=xgQG>VC~VY#gI;W zTTbce5cHzr`Hg@4OdhH={8PIycBXV%uB|)X=^!DRXTmEtJcv3;m^2e_;ixY%pHxNZ z<%)Yr;VPTKH1g`z|8A}lV1iLp2|*G*^Yf9jH=@^=W5p36!uD@oi+MWzbEfch>^qCC z4JG(tRlc)vEWuOBzZ1YAbR3kz7)&FEH+?^2^O>ZZKW$a|hI#&d*wtwjFBN6K z^{lpx3YE|qcsSJq)bz#@zAB(+lGP8@dLlA!z zREGbG%!ZwP?;7cE`>TvsAml(q15E4$QhLs4%bfNSZEa<`z3SkoCp61U%j+1 Ht6 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 IuHE_n0B{u|=>Px# literal 0 HcmV?d00001 diff --git a/databricks-iris/prompts.yml b/databricks-iris/prompts.yml new file mode 100644 index 00000000..7e4bf62f --- /dev/null +++ b/databricks-iris/prompts.yml @@ -0,0 +1,9 @@ +project_name: + title: "Project Name" + text: | + Please enter a human readable name for your new project. + Spaces, hyphens, and underscores are allowed. + regex_validator: "^[\\w -]{2,}$" + error_message: | + It must contain only alphanumeric symbols, spaces, underscores and hyphens and + be at least 2 characters long. diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/.gitignore b/databricks-iris/{{ cookiecutter.repo_name }}/.gitignore new file mode 100644 index 00000000..f2b2bd0e --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/.gitignore @@ -0,0 +1,152 @@ +########################## +# KEDRO PROJECT + +# ignore all local configuration +conf/local/** +!conf/local/.gitkeep + +# ignore potentially sensitive credentials files +conf/**/*credentials* + +# ignore everything in the following folders +data/** + +# except their sub-folders +!data/**/ + +# also keep all .gitkeep files +!.gitkeep + +# also keep the example dataset +!data/01_raw/*.csv + + +########################## +# Common files + +# IntelliJ +.idea/ +*.iml +out/ +.idea_modules/ + +### macOS +*.DS_Store +.AppleDouble +.LSOverride +.Trashes + +# Vim +*~ +.*.swo +.*.swp + +# emacs +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc + +# JIRA plugin +atlassian-ide-plugin.xml + +# C extensions +*.so + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/README.md b/databricks-iris/{{ cookiecutter.repo_name }}/README.md new file mode 100644 index 00000000..5a07de4f --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/README.md @@ -0,0 +1,122 @@ +# {{ cookiecutter.project_name }} + +## Overview + +This is your new Kedro project, which was generated using `Kedro {{ cookiecutter.kedro_version }}`. + +Take a look at the [Kedro documentation](https://kedro.readthedocs.io) to get started. + +## Rules and guidelines + +In order to get the best out of the template: + +* Don't remove any lines from the `.gitignore` file we provide +* Make sure your results can be reproduced by following a [data engineering convention](https://kedro.readthedocs.io/en/stable/faq/faq.html#what-is-data-engineering-convention) +* Don't commit data to your repository +* Don't commit any credentials or your local configuration to your repository. Keep all your credentials and local configuration in `conf/local/` + +## How to install dependencies + +Declare any dependencies in `src/requirements.txt` for `pip` installation and `src/environment.yml` for `conda` installation. + +To install them, run: + +``` +pip install -r src/requirements.txt +``` + +## How to run your Kedro pipeline + +You can run your Kedro project with: + +``` +kedro run +``` + +## How to test your Kedro project + +Have a look at the file `src/tests/test_run.py` for instructions on how to write your tests. You can run your tests as follows: + +``` +kedro test +``` + +To configure the coverage threshold, go to the `.coveragerc` file. + +## Project dependencies + +To generate or update the dependency requirements for your project: + +``` +kedro build-reqs +``` + +This will `pip-compile` the contents of `src/requirements.txt` into a new file `src/requirements.lock`. You can see the output of the resolution by opening `src/requirements.lock`. + +After this, if you'd like to update your project requirements, please update `src/requirements.txt` and re-run `kedro build-reqs`. + +[Further information about project dependencies](https://kedro.readthedocs.io/en/stable/kedro_project_setup/dependencies.html#project-specific-dependencies) + +## How to work with Kedro and notebooks + +> Note: Using `kedro jupyter` or `kedro ipython` to run your notebook provides these variables in scope: `catalog`, `context`, `pipelines` and `session`. +> +> Jupyter, JupyterLab, and IPython are already included in the project requirements by default, so once you have run `pip install -r src/requirements.txt` you will not need to take any extra steps before you use them. + +### Jupyter +To use Jupyter notebooks in your Kedro project, you need to install Jupyter: + +``` +pip install jupyter +``` + +After installing Jupyter, you can start a local notebook server: + +``` +kedro jupyter notebook +``` + +### JupyterLab +To use JupyterLab, you need to install it: + +``` +pip install jupyterlab +``` + +You can also start JupyterLab: + +``` +kedro jupyter lab +``` + +### IPython +And if you want to run an IPython session: + +``` +kedro ipython +``` + +### How to convert notebook cells to nodes in a Kedro project +You can move notebook code over into a Kedro project structure using a mixture of [cell tagging](https://jupyter-notebook.readthedocs.io/en/stable/changelog.html#release-5-0-0) and Kedro CLI commands. + +By adding the `node` tag to a cell and running the command below, the cell's source code will be copied over to a Python file within `src//nodes/`: + +``` +kedro jupyter convert +``` +> *Note:* The name of the Python file matches the name of the original notebook. + +Alternatively, you may want to transform all your notebooks in one go. Run the following command to convert all notebook files found in the project root directory and under any of its sub-folders: + +``` +kedro jupyter convert --all +``` + +### How to ignore notebook output cells in `git` +To automatically strip out all output cell contents before committing to `git`, you can run `kedro activate-nbstripout`. This will add a hook in `.git/config` which will run `nbstripout` before anything is committed to `git`. + +> *Note:* Your output cells will be retained locally. + +## Package your Kedro project + +[Further information about building project documentation and packaging your project](https://kedro.readthedocs.io/en/stable/tutorial/package_a_project.html) diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/conf/README.md b/databricks-iris/{{ cookiecutter.repo_name }}/conf/README.md new file mode 100644 index 00000000..a6a80a42 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/conf/README.md @@ -0,0 +1,26 @@ +# What is this for? + +This folder should be used to store configuration files used by Kedro or by separate tools. + +This file can be used to provide users with instructions for how to reproduce local configuration with their own credentials. You can edit the file however you like, but you may wish to retain the information below and add your own section in the [Instructions](#Instructions) section. + +## Local configuration + +The `local` folder should be used for configuration that is either user-specific (e.g. IDE configuration) or protected (e.g. security keys). + +> *Note:* Please do not check in any local configuration to version control. + +## Base configuration + +The `base` folder is for shared configuration, such as non-sensitive and project-related configuration that may be shared across team members. + +WARNING: Please do not put access credentials in the base configuration folder. + +## Instructions + + + + + +## Find out more +You can find out more about configuration from the [user guide documentation](https://kedro.readthedocs.io/en/stable/user_guide/configuration.html). diff --git a/pyspark-iris/{{ cookiecutter.repo_name }}/conf/databricks/catalog.yml b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/catalog.yml similarity index 79% rename from pyspark-iris/{{ cookiecutter.repo_name }}/conf/databricks/catalog.yml rename to databricks-iris/{{ cookiecutter.repo_name }}/conf/base/catalog.yml index 3307e014..061d16e3 100644 --- a/pyspark-iris/{{ cookiecutter.repo_name }}/conf/databricks/catalog.yml +++ b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/catalog.yml @@ -56,43 +56,43 @@ example_iris_data: # for all SparkDataSets. X_train@pyspark: type: spark.SparkDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/X_train.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/X_train.parquet save_args: mode: overwrite X_train@pandas: type: pandas.ParquetDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/X_train.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/X_train.parquet X_test@pyspark: type: spark.SparkDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/X_test.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/X_test.parquet save_args: mode: overwrite X_test@pandas: type: pandas.ParquetDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/X_test.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/X_test.parquet y_train@pyspark: type: spark.SparkDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/y_train.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/y_train.parquet save_args: mode: overwrite y_train@pandas: type: pandas.ParquetDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/y_train.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/y_train.parquet y_test@pyspark: type: spark.SparkDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/y_test.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/y_test.parquet save_args: mode: overwrite y_test@pandas: type: pandas.ParquetDataSet - filepath: /dbfs/root/projects/iris-databricks/data/02_intermediate/y_test.parquet + filepath: /dbfs/FileStore/iris-databricks/data/02_intermediate/y_test.parquet # This is an example how to use `MemoryDataSet` with Spark objects that aren't `DataFrame`'s. # In particular, the `assign` copy mode ensures that the `MemoryDataSet` will be assigned diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/logging.yml b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/logging.yml new file mode 100644 index 00000000..5b63e37e --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/logging.yml @@ -0,0 +1,32 @@ +version: 1 + +disable_existing_loggers: False + +formatters: + simple: + format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + +handlers: + info_file_handler: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: simple + filename: /dbfs/FileStore/iris-databricks/info.log + maxBytes: 10485760 # 10MB + backupCount: 20 + encoding: utf8 + delay: True + +loggers: + kedro: + level: INFO + + iris_databricks: + level: INFO + +root: + # File-based logging is disabled by default so that the starter works immediately on Databricks Repos. + # See https://docs.kedro.org/en/stable/logging/logging.html#disable-file-based-logging for more. + # To enable file-based logging, change the below line to: + # handlers: [rich, info_file_handler] + handlers: [info_file_handler] diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/parameters.yml b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/parameters.yml new file mode 100644 index 00000000..48c3cd72 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/parameters.yml @@ -0,0 +1,3 @@ +train_fraction: 0.8 +random_state: 3 +target_column: species diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/spark.yml b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/spark.yml new file mode 100644 index 00000000..ab831b62 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/conf/base/spark.yml @@ -0,0 +1,8 @@ +# You can define spark specific configuration here. + +spark.driver.maxResultSize: 3g +spark.hadoop.fs.s3a.impl: org.apache.hadoop.fs.s3a.S3AFileSystem +spark.sql.execution.arrow.pyspark.enabled: true + +# https://docs.kedro.org/en/stable/integrations/pyspark_integration.html#tips-for-maximising-concurrency-using-threadrunner +spark.scheduler.mode: FAIR diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/conf/local/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/conf/local/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/iris.csv b/databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/iris.csv new file mode 100644 index 00000000..ba0ebd24 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/data/01_raw/iris.csv @@ -0,0 +1,151 @@ +sepal_length,sepal_width,petal_length,petal_width,species +5.1,3.5,1.4,0.2,setosa +4.9,3.0,1.4,0.2,setosa +4.7,3.2,1.3,0.2,setosa +4.6,3.1,1.5,0.2,setosa +5.0,3.6,1.4,0.2,setosa +5.4,3.9,1.7,0.4,setosa +4.6,3.4,1.4,0.3,setosa +5.0,3.4,1.5,0.2,setosa +4.4,2.9,1.4,0.2,setosa +4.9,3.1,1.5,0.1,setosa +5.4,3.7,1.5,0.2,setosa +4.8,3.4,1.6,0.2,setosa +4.8,3.0,1.4,0.1,setosa +4.3,3.0,1.1,0.1,setosa +5.8,4.0,1.2,0.2,setosa +5.7,4.4,1.5,0.4,setosa +5.4,3.9,1.3,0.4,setosa +5.1,3.5,1.4,0.3,setosa +5.7,3.8,1.7,0.3,setosa +5.1,3.8,1.5,0.3,setosa +5.4,3.4,1.7,0.2,setosa +5.1,3.7,1.5,0.4,setosa +4.6,3.6,1.0,0.2,setosa +5.1,3.3,1.7,0.5,setosa +4.8,3.4,1.9,0.2,setosa +5.0,3.0,1.6,0.2,setosa +5.0,3.4,1.6,0.4,setosa +5.2,3.5,1.5,0.2,setosa +5.2,3.4,1.4,0.2,setosa +4.7,3.2,1.6,0.2,setosa +4.8,3.1,1.6,0.2,setosa +5.4,3.4,1.5,0.4,setosa +5.2,4.1,1.5,0.1,setosa +5.5,4.2,1.4,0.2,setosa +4.9,3.1,1.5,0.1,setosa +5.0,3.2,1.2,0.2,setosa +5.5,3.5,1.3,0.2,setosa +4.9,3.1,1.5,0.1,setosa +4.4,3.0,1.3,0.2,setosa +5.1,3.4,1.5,0.2,setosa +5.0,3.5,1.3,0.3,setosa +4.5,2.3,1.3,0.3,setosa +4.4,3.2,1.3,0.2,setosa +5.0,3.5,1.6,0.6,setosa +5.1,3.8,1.9,0.4,setosa +4.8,3.0,1.4,0.3,setosa +5.1,3.8,1.6,0.2,setosa +4.6,3.2,1.4,0.2,setosa +5.3,3.7,1.5,0.2,setosa +5.0,3.3,1.4,0.2,setosa +7.0,3.2,4.7,1.4,versicolor +6.4,3.2,4.5,1.5,versicolor +6.9,3.1,4.9,1.5,versicolor +5.5,2.3,4.0,1.3,versicolor +6.5,2.8,4.6,1.5,versicolor +5.7,2.8,4.5,1.3,versicolor +6.3,3.3,4.7,1.6,versicolor +4.9,2.4,3.3,1.0,versicolor +6.6,2.9,4.6,1.3,versicolor +5.2,2.7,3.9,1.4,versicolor +5.0,2.0,3.5,1.0,versicolor +5.9,3.0,4.2,1.5,versicolor +6.0,2.2,4.0,1.0,versicolor +6.1,2.9,4.7,1.4,versicolor +5.6,2.9,3.6,1.3,versicolor +6.7,3.1,4.4,1.4,versicolor +5.6,3.0,4.5,1.5,versicolor +5.8,2.7,4.1,1.0,versicolor +6.2,2.2,4.5,1.5,versicolor +5.6,2.5,3.9,1.1,versicolor +5.9,3.2,4.8,1.8,versicolor +6.1,2.8,4.0,1.3,versicolor +6.3,2.5,4.9,1.5,versicolor +6.1,2.8,4.7,1.2,versicolor +6.4,2.9,4.3,1.3,versicolor +6.6,3.0,4.4,1.4,versicolor +6.8,2.8,4.8,1.4,versicolor +6.7,3.0,5.0,1.7,versicolor +6.0,2.9,4.5,1.5,versicolor +5.7,2.6,3.5,1.0,versicolor +5.5,2.4,3.8,1.1,versicolor +5.5,2.4,3.7,1.0,versicolor +5.8,2.7,3.9,1.2,versicolor +6.0,2.7,5.1,1.6,versicolor +5.4,3.0,4.5,1.5,versicolor +6.0,3.4,4.5,1.6,versicolor +6.7,3.1,4.7,1.5,versicolor +6.3,2.3,4.4,1.3,versicolor +5.6,3.0,4.1,1.3,versicolor +5.5,2.5,4.0,1.3,versicolor +5.5,2.6,4.4,1.2,versicolor +6.1,3.0,4.6,1.4,versicolor +5.8,2.6,4.0,1.2,versicolor +5.0,2.3,3.3,1.0,versicolor +5.6,2.7,4.2,1.3,versicolor +5.7,3.0,4.2,1.2,versicolor +5.7,2.9,4.2,1.3,versicolor +6.2,2.9,4.3,1.3,versicolor +5.1,2.5,3.0,1.1,versicolor +5.7,2.8,4.1,1.3,versicolor +6.3,3.3,6.0,2.5,virginica +5.8,2.7,5.1,1.9,virginica +7.1,3.0,5.9,2.1,virginica +6.3,2.9,5.6,1.8,virginica +6.5,3.0,5.8,2.2,virginica +7.6,3.0,6.6,2.1,virginica +4.9,2.5,4.5,1.7,virginica +7.3,2.9,6.3,1.8,virginica +6.7,2.5,5.8,1.8,virginica +7.2,3.6,6.1,2.5,virginica +6.5,3.2,5.1,2.0,virginica +6.4,2.7,5.3,1.9,virginica +6.8,3.0,5.5,2.1,virginica +5.7,2.5,5.0,2.0,virginica +5.8,2.8,5.1,2.4,virginica +6.4,3.2,5.3,2.3,virginica +6.5,3.0,5.5,1.8,virginica +7.7,3.8,6.7,2.2,virginica +7.7,2.6,6.9,2.3,virginica +6.0,2.2,5.0,1.5,virginica +6.9,3.2,5.7,2.3,virginica +5.6,2.8,4.9,2.0,virginica +7.7,2.8,6.7,2.0,virginica +6.3,2.7,4.9,1.8,virginica +6.7,3.3,5.7,2.1,virginica +7.2,3.2,6.0,1.8,virginica +6.2,2.8,4.8,1.8,virginica +6.1,3.0,4.9,1.8,virginica +6.4,2.8,5.6,2.1,virginica +7.2,3.0,5.8,1.6,virginica +7.4,2.8,6.1,1.9,virginica +7.9,3.8,6.4,2.0,virginica +6.4,2.8,5.6,2.2,virginica +6.3,2.8,5.1,1.5,virginica +6.1,2.6,5.6,1.4,virginica +7.7,3.0,6.1,2.3,virginica +6.3,3.4,5.6,2.4,virginica +6.4,3.1,5.5,1.8,virginica +6.0,3.0,4.8,1.8,virginica +6.9,3.1,5.4,2.1,virginica +6.7,3.1,5.6,2.4,virginica +6.9,3.1,5.1,2.3,virginica +5.8,2.7,5.1,1.9,virginica +6.8,3.2,5.9,2.3,virginica +6.7,3.3,5.7,2.5,virginica +6.7,3.0,5.2,2.3,virginica +6.3,2.5,5.0,1.9,virginica +6.5,3.0,5.2,2.0,virginica +6.2,3.4,5.4,2.3,virginica +5.9,3.0,5.1,1.8,virginica diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/02_intermediate/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/02_intermediate/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/03_primary/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/03_primary/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/04_feature/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/04_feature/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/05_model_input/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/05_model_input/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/06_models/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/06_models/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/07_model_output/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/07_model_output/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/data/08_reporting/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/data/08_reporting/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/conf.py b/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/conf.py new file mode 100644 index 00000000..740fa356 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/conf.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 + + +# {{ cookiecutter.python_package }} documentation build +# configuration file, created by sphinx-quickstart. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import re + +from kedro.framework.cli.utils import find_stylesheets + +from {{ cookiecutter.python_package }} import __version__ as release + +# -- Project information ----------------------------------------------------- + +project = "{{ cookiecutter.python_package }}" +author = "Kedro" + +# The short X.Y version. +version = re.match(r"^([0-9]+\.[0-9]+).*", release).group(1) + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx_autodoc_typehints", + "sphinx.ext.doctest", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", + "sphinx.ext.mathjax", + "nbsphinx", + "sphinx_copybutton", + "myst_parser", +] + +# enable autosummary plugin (table of contents for modules/classes/class +# methods) +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = {".rst": "restructuredtext", ".md": "markdown"} + +# The master toctree document. +master_doc = "index" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# 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 + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = ["_build", "**.ipynb_checkpoints"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = {"collapse_navigation": False, "style_external_links": True} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + +html_show_sourcelink = False + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = "{{ cookiecutter.python_package }}doc" + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ( + master_doc, + "{{ cookiecutter.python_package }}.tex", + "{{ cookiecutter.python_package }} Documentation", + "Kedro", + "manual", + ) +] + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ( + master_doc, + "{{ cookiecutter.python_package }}", + "{{ cookiecutter.python_package }} Documentation", + [author], + 1, + ) +] + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + master_doc, + "{{ cookiecutter.python_package }}", + "{{ cookiecutter.python_package }} Documentation", + author, + "{{ cookiecutter.python_package }}", + "Project {{ cookiecutter.python_package }} codebase.", + "Nearest-Neighbour", + ) +] + +# -- Options for todo extension ---------------------------------------------- + +# 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 +# """ + +# -- NBconvert kernel config ------------------------------------------------- +nbsphinx_kernel_name = "python3" + + +def remove_arrows_in_examples(lines): + for i, line in enumerate(lines): + lines[i] = line.replace(">>>", "") + + +def autodoc_process_docstring(app, what, name, obj, options, lines): + remove_arrows_in_examples(lines) + + +def skip(app, what, name, obj, skip, options): + if name == "__init__": + return False + return skip + + +def setup(app): + app.connect("autodoc-process-docstring", autodoc_process_docstring) + app.connect("autodoc-skip-member", skip) + # add Kedro stylesheets + for stylesheet in find_stylesheets(): + app.add_css_file(stylesheet) + # enable rendering RST tables in Markdown diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/index.rst b/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/index.rst new file mode 100644 index 00000000..06252d32 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/docs/source/index.rst @@ -0,0 +1,19 @@ +.. {{ cookiecutter.python_package }} documentation master file, created by sphinx-quickstart. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to project {{ cookiecutter.python_package }}'s API docs! +============================================= + +.. toctree:: + :maxdepth: 4 + + modules + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/notebooks/.gitkeep b/databricks-iris/{{ cookiecutter.repo_name }}/notebooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/pyproject.toml b/databricks-iris/{{ cookiecutter.repo_name }}/pyproject.toml new file mode 100644 index 00000000..7ae06368 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/pyproject.toml @@ -0,0 +1,17 @@ +[tool.kedro] +package_name = "{{ cookiecutter.python_package }}" +project_name = "{{ cookiecutter.project_name }}" +kedro_init_version = "{{ cookiecutter.kedro_version }}" + +[tool.isort] +profile = "black" + +[tool.pytest.ini_options] +addopts = """ +--cov-report term-missing \ +--cov src/{{ cookiecutter.python_package }} -ra""" + +[tool.coverage.report] +fail_under = 0 +show_missing = true +exclude_lines = ["pragma: no cover", "raise NotImplementedError"] diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/setup.cfg b/databricks-iris/{{ cookiecutter.repo_name }}/setup.cfg new file mode 100644 index 00000000..63ea6730 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +max-line-length=88 +extend-ignore=E203 diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/requirements.txt b/databricks-iris/{{ cookiecutter.repo_name }}/src/requirements.txt new file mode 100644 index 00000000..9d822588 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/requirements.txt @@ -0,0 +1,16 @@ +black~=22.0 +flake8>=3.7.9, <4.0 +ipython>=7.31.1, <8.0; python_version < '3.8' +ipython~=8.10; python_version >= '3.8' +isort~=5.0 +jupyter~=1.0 +jupyterlab~=3.0 +kedro~={{ cookiecutter.kedro_version }} +kedro-datasets[spark.SparkDataSet, pandas.ParquetDataSet]~=1.0.0 +kedro-telemetry~=0.2.0 +nbstripout~=0.4 +numpy~=1.21 +pytest-cov~=3.0 +pytest-mock>=1.7.1, <2.0 +pytest~=7.2 + diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/setup.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/setup.py new file mode 100644 index 00000000..ee21a4f4 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/setup.py @@ -0,0 +1,39 @@ +from setuptools import find_packages, setup + +entry_point = ( + "databricks_run = {{ cookiecutter.python_package }}.databricks_run:main" +) + + +# get the dependencies and installs +with open("requirements.txt", encoding="utf-8") as f: + # Make sure we strip all comments and options (e.g "--extra-index-url") + # that arise from a modified pip.conf file that configure global options + # when running kedro build-reqs + requires = [] + for line in f: + req = line.split("#", 1)[0].strip() + if req and not req.startswith("--"): + requires.append(req) + +setup( + name="{{ cookiecutter.python_package }}", + version="0.1", + packages=find_packages(exclude=["tests"]), + entry_points={"console_scripts": [entry_point]}, + install_requires=requires, + extras_require={ + "docs": [ + "docutils<0.18.0", + "sphinx~=3.4.3", + "sphinx_rtd_theme==0.5.1", + "nbsphinx==0.8.1", + "nbstripout~=0.4", + "myst-parser~=0.17.2", + "sphinx-autodoc-typehints==1.11.1", + "sphinx_copybutton==0.3.1", + "ipykernel>=5.3, <7.0", + "Jinja2<3.1.0", + ] + }, +) diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/__init__.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_pipeline.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_pipeline.py new file mode 100644 index 00000000..2cdf4269 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_pipeline.py @@ -0,0 +1,9 @@ +""" +This is a boilerplate test file +generated using Kedro {{ cookiecutter.kedro_version }}. +Please add your pipeline tests here. + +Kedro recommends using `pytest` framework, more info about it can be found +in the official documentation: +https://docs.pytest.org/en/latest/getting-started.html +""" diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_run.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_run.py new file mode 100644 index 00000000..059aeac8 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/tests/test_run.py @@ -0,0 +1,39 @@ +""" +This module contains an example test. + +Tests should be placed in ``src/tests``, in modules that mirror your +project's structure, and in files named test_*.py. They are simply functions +named ``test_*`` which test a unit of logic. + +To run the tests, run ``kedro test`` from the project root directory. +""" + +from pathlib import Path + +import pytest +from kedro.config import ConfigLoader +from kedro.framework.context import KedroContext +from kedro.framework.hooks import _create_hook_manager + + +@pytest.fixture +def config_loader(): + return ConfigLoader(conf_source=str(Path.cwd())) + + +@pytest.fixture +def project_context(config_loader): + return KedroContext( + package_name="{{ cookiecutter.python_package }}", + project_path=Path.cwd(), + config_loader=config_loader, + hook_manager=_create_hook_manager(), + ) + + +# The tests below are here for the demonstration purpose +# and should be replaced with the ones testing the project +# functionality +class TestProjectContext: + def test_project_path(self, project_context): + assert project_context.project_path == Path.cwd() diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/README.md b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/README.md new file mode 100644 index 00000000..01b31808 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/README.md @@ -0,0 +1,72 @@ +# Pipeline + +> *Note:* This is a `README.md` boilerplate generated using `Kedro {{ cookiecutter.kedro_version }}`. + +## Overview + +[Transcoding](https://kedro.readthedocs.io/en/stable/data/data_catalog.html#transcoding-datasets) is used to convert the Spark DataFrames into pandas DataFrames after splitting the data into training and testing sets. + +This pipeline: +1. splits the data into training dataset and testing dataset using a configurable ratio found in `conf/base/parameters.yml` +2. runs a simple 1-nearest neighbour model (`make_prediction` node) and makes prediction dataset +3. reports the model accuracy on a test set (`report_accuracy` node) + +## Pipeline inputs + +### `example_iris_data` + +| | | +| ---- | ------------------ | +| Type | `spark.SparkDataSet` | +| Description | Example iris data containing columns | + + +### `parameters` + +| | | +| ---- | ------------------ | +| Type | `dict` | +| Description | Project parameter dictionary that must contain the following keys: `train_fraction` (the ratio used to determine the train-test split), `random_state` (random generator to ensure train-test split is deterministic) and `target_column` (identify the target column in the dataset) | + + +## Pipeline intermediate outputs + +### `X_train` + +| | | +| ---- | ------------------ | +| Type | `pyspark.sql.DataFrame` | +| Description | DataFrame containing train set features | + +### `y_train` + +| | | +| ---- | ------------------ | +| Type | `pyspark.sql.DataFrame` | +| Description | Series containing train set target | + +### `X_test` + +| | | +| ---- | ------------------ | +| Type | `pyspark.sql.DataFrame` | +| Description | DataFrame containing test set features | + +### `y_test` + +| | | +| ---- | ------------------ | +| Type | `pyspark.sql.DataFrame` | +| Description | Series containing test set target | + +### `y_pred` + +| | | +| ---- | ------------------ | +| Type | `pandas.Series` | +| Description | Predictions from the 1-nearest neighbour model | + + +## Pipeline outputs + +### `None` \ No newline at end of file diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/__init__.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/__init__.py new file mode 100644 index 00000000..177bba98 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/__init__.py @@ -0,0 +1,4 @@ +"""{{ cookiecutter.project_name }} +""" + +__version__ = "0.1" diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/databricks_run.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/databricks_run.py new file mode 100644 index 00000000..fac518fb --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/databricks_run.py @@ -0,0 +1,29 @@ +import argparse +import logging + +from kedro.framework.project import configure_project +from kedro.framework.session import KedroSession + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--env", dest="env", type=str) + parser.add_argument("--conf-source", dest="conf_source", type=str) + parser.add_argument("--package-name", dest="package_name", type=str) + + args = parser.parse_args() + env = args.env + conf_source = args.conf_source + package_name = args.package_name + + # https://kb.databricks.com/notebooks/cmd-c-on-object-id-p0.html + logging.getLogger("py4j.java_gateway").setLevel(logging.ERROR) + logging.getLogger("py4j.py4j.clientserver").setLevel(logging.ERROR) + + configure_project(package_name) + with KedroSession.create(env=env, conf_source=conf_source) as session: + session.run() + + +if __name__ == "__main__": + main() diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/hooks.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/hooks.py new file mode 100644 index 00000000..39966779 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/hooks.py @@ -0,0 +1,24 @@ +from kedro.framework.hooks import hook_impl +from pyspark import SparkConf +from pyspark.sql import SparkSession + + +class SparkHooks: + @hook_impl + def after_context_created(self, context) -> None: + """Initialises a SparkSession using the config + defined in project's conf folder. + """ + + # Load the spark configuration in spark.yaml using the config loader + parameters = context.config_loader.get("spark*", "spark*/**") + spark_conf = SparkConf().setAll(parameters.items()) + + # Initialise the spark session + spark_session_conf = ( + SparkSession.builder.appName(context.project_path.name) + .enableHiveSupport() + .config(conf=spark_conf) + ) + _spark_session = spark_session_conf.getOrCreate() + _spark_session.sparkContext.setLogLevel("WARN") diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/nodes.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/nodes.py new file mode 100644 index 00000000..365bd796 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/nodes.py @@ -0,0 +1,73 @@ +""" +This is a boilerplate pipeline +generated using Kedro {{ cookiecutter.kedro_version }} +""" + +import logging +from typing import Dict, Tuple + +import numpy as np +import pandas as pd +from pyspark.sql import DataFrame + + +def split_data(data: DataFrame, parameters: Dict) -> Tuple: + """Splits data into features and targets training and test sets. + + Args: + data: Data containing features and target. + parameters: Parameters defined in parameters.yml. + Returns: + Split data. + """ + + # Split to training and testing data + data_train, data_test = data.randomSplit( + weights=[parameters["train_fraction"], 1 - parameters["train_fraction"]] + ) + + X_train = data_train.drop(parameters["target_column"]) + X_test = data_test.drop(parameters["target_column"]) + y_train = data_train.select(parameters["target_column"]) + y_test = data_test.select(parameters["target_column"]) + + return X_train, X_test, y_train, y_test + + +def make_predictions( + X_train: pd.DataFrame, X_test: pd.DataFrame, y_train: pd.DataFrame +) -> DataFrame: + """Uses 1-nearest neighbour classifier to create predictions. + + Args: + X_train: Training data of features. + y_train: Training data for target. + X_test: Test data for features. + + Returns: + y_pred: Prediction of the target variable. + """ + + X_train_numpy = X_train.to_numpy() + X_test_numpy = X_test.to_numpy() + + squared_distances = np.sum( + (X_train_numpy[:, None, :] - X_test_numpy[None, :, :]) ** 2, axis=-1 + ) + nearest_neighbour = squared_distances.argmin(axis=0) + y_pred = y_train.iloc[nearest_neighbour] + y_pred.index = X_test.index + + return y_pred + + +def report_accuracy(y_pred: pd.Series, y_test: pd.Series): + """Calculates and logs the accuracy. + + Args: + y_pred: Predicted target. + y_test: True target. + """ + accuracy = (y_pred == y_test).sum() / len(y_test) + logger = logging.getLogger(__name__) + logger.info("Model has an accuracy of %.3f on test data.", accuracy) diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline.py new file mode 100644 index 00000000..119c58fa --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline.py @@ -0,0 +1,38 @@ +""" +This is a boilerplate pipeline +generated using Kedro {{ cookiecutter.kedro_version }} +""" + +from kedro.pipeline import Pipeline, node, pipeline + +from .nodes import make_predictions, report_accuracy, split_data + + +def create_pipeline(**kwargs) -> Pipeline: + return pipeline( + [ + node( + func=split_data, + inputs=["example_iris_data", "parameters"], + outputs=[ + "X_train@pyspark", + "X_test@pyspark", + "y_train@pyspark", + "y_test@pyspark", + ], + name="split", + ), + node( + func=make_predictions, + inputs=["X_train@pandas", "X_test@pandas", "y_train@pandas"], + outputs="y_pred", + name="make_predictions", + ), + node( + func=report_accuracy, + inputs=["y_pred", "y_test@pandas"], + outputs=None, + name="report_accuracy", + ), + ] + ) diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline_registry.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline_registry.py new file mode 100644 index 00000000..2d4272e3 --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/pipeline_registry.py @@ -0,0 +1,16 @@ +"""Project pipelines.""" +from typing import Dict + +from kedro.framework.project import find_pipelines +from kedro.pipeline import Pipeline + + +def register_pipelines() -> Dict[str, Pipeline]: + """Register the project's pipelines. + + Returns: + A mapping from pipeline names to ``Pipeline`` objects. + """ + pipelines = find_pipelines() + pipelines["__default__"] = sum(pipelines.values()) + return pipelines diff --git a/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/settings.py b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/settings.py new file mode 100644 index 00000000..e5593b1c --- /dev/null +++ b/databricks-iris/{{ cookiecutter.repo_name }}/src/{{ cookiecutter.python_package }}/settings.py @@ -0,0 +1,38 @@ +"""Project settings. There is no need to edit this file unless you want to change values +from the Kedro defaults. For further information, including these default values, see +https://kedro.readthedocs.io/en/stable/kedro_project_setup/settings.html.""" + +# Instantiated project hooks. +from {{cookiecutter.python_package}}.hooks import SparkHooks + +HOOKS = (SparkHooks(),) + +# Installed plugins for which to disable hook auto-registration. +# DISABLE_HOOKS_FOR_PLUGINS = ("kedro-viz",) + +# Class that manages storing KedroSession data. +# from kedro.framework.session.shelvestore import ShelveStore +# SESSION_STORE_CLASS = ShelveStore +# Keyword arguments to pass to the `SESSION_STORE_CLASS` constructor. +# SESSION_STORE_ARGS = { +# "path": "./sessions" +# } + +# Class that manages Kedro's library components. +# from kedro.framework.context import KedroContext +# CONTEXT_CLASS = KedroContext + +# Directory that holds configuration. +# CONF_SOURCE = "conf" + +# Class that manages how configuration is loaded. +# from kedro.config import TemplatedConfigLoader +# CONFIG_LOADER_CLASS = TemplatedConfigLoader +# Keyword arguments to pass to the `CONFIG_LOADER_CLASS` constructor. +# CONFIG_LOADER_ARGS = { +# "globals_pattern": "*globals.yml", +# } + +# Class that manages the Data Catalog. +# from kedro.io import DataCatalog +# DATA_CATALOG_CLASS = DataCatalog