diff --git a/.github/workflows/test_coverage.yml b/.github/workflows/test_coverage.yml index ba42d8010..16416d9d6 100644 --- a/.github/workflows/test_coverage.yml +++ b/.github/workflows/test_coverage.yml @@ -41,7 +41,7 @@ jobs: - name: clean environment run: | - export backup_files=( tests tutorials .env_file makefile .coveragerc ) + export backup_files=( tests tutorials .env_file makefile .coveragerc pytest.ini docs ) mkdir /tmp/backup for i in "${backup_files[@]}" ; do mv "$i" /tmp/backup ; done rm -rf ..?* .[!.]* * diff --git a/.github/workflows/test_full.yml b/.github/workflows/test_full.yml index ff1be82e6..66134f756 100644 --- a/.github/workflows/test_full.yml +++ b/.github/workflows/test_full.yml @@ -48,7 +48,7 @@ jobs: source <(cat .env_file | sed 's/=/=/' | sed 's/^/export /') pytest --tb=long -vv --cache-clear --no-cov --allow-skip=telegram tests/ else - pytest --tb=long -vv --cache-clear --no-cov --allow-skip=telegram,docker tests/ + pytest -m "not docker" --tb=long -vv --cache-clear --no-cov --allow-skip=telegram,docker tests/ fi shell: bash test_no_deps: diff --git a/docs/source/conf.py b/docs/source/conf.py index 74415dc7b..4bc3731dd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -5,7 +5,7 @@ # -- Path setup -------------------------------------------------------------- sys.path.append(os.path.abspath(".")) -from utils.notebook import insert_installation_cell_into_py_tutorial # noqa: E402 +from utils.notebook import py_percent_to_notebook # noqa: E402 from utils.generate_tutorials import generate_tutorial_links_for_notebook_creation # noqa: E402 from utils.regenerate_apiref import regenerate_apiref # noqa: E402 @@ -87,7 +87,7 @@ autosummary_generate_overwrite = False # Finding tutorials directories -nbsphinx_custom_formats = {".py": insert_installation_cell_into_py_tutorial()} +nbsphinx_custom_formats = {".py": py_percent_to_notebook} nbsphinx_prolog = """ :tutorial_name: {{ env.docname }} """ diff --git a/docs/source/utils/notebook.py b/docs/source/utils/notebook.py index 0133c70f7..587faeba1 100644 --- a/docs/source/utils/notebook.py +++ b/docs/source/utils/notebook.py @@ -1,42 +1,154 @@ -from jupytext import jupytext +import re +import abc +from typing import ClassVar, Literal, Optional +from pydantic import BaseModel -def insert_installation_cell_into_py_tutorial(): +try: + from jupytext import jupytext +except ImportError: + jupytext = None + + +class ReplacePattern(BaseModel, abc.ABC): """ - This function modifies a Jupyter notebook by inserting a code cell for installing 'dff' package - and its dependencies, and a markdown cell with instructions for the user. It uses the location of - the second cell in the notebook as a reference point to insert the new cells. + An interface for replace patterns. """ - def inner(tutorial_text: str): - second_cell = tutorial_text.find("\n# %%", 5) - return jupytext.reads( - f"""{tutorial_text[:second_cell]} + @property + @abc.abstractmethod + def pattern(self) -> re.Pattern: + """ + A regex pattern to replace in a text. + """ + ... + + @staticmethod + @abc.abstractmethod + def replacement_string(matchobj: re.Match) -> str: + """ + Return a replacement string for a match object. + + :param matchobj: A regex match object. + :return: A string to replace match with. + """ + ... + + @classmethod + def replace(cls, text: str) -> str: + """ + Replace all instances of `pattern` in `text` with the result of `replacement_string`. + + :param text: A text in which patterns are replaced. + :return: A string with patterns replaced. + """ + return re.sub(cls.pattern, cls.replacement_string, text) + + +class InstallationCell(ReplacePattern): + """ + Replace installation cells directives. + + Uncomment `# %pip install {}`, add a "quiet" flag, add a comment explaining the cell. + """ -# %% [markdown] -\"\"\" -__Installing dependencies__ -\"\"\" + pattern: ClassVar[re.Pattern] = re.compile("\n# %pip install (.*)\n") + @staticmethod + def replacement_string(matchobj: re.Match) -> str: + return f""" # %% -!python3 -m pip install -q dff[tutorials] -# Installs dff with dependencies for running tutorials -# To install the minimal version of dff, use `pip install dff` -# To install other options of dff, use `pip install dff[OPTION_NAME1,OPTION_NAME2]` -# where OPTION_NAME can be one of the options from EXTRA_DEPENDENCIES. -# e.g `pip install dff[ydb, mysql]` installs dff with dependencies for using Yandex Database and MySQL -# EXTRA_DEPENDENCIES can be found in -# https://github.com/deeppavlov/dialog_flow_framework/blob/dev/README.md#installation - - -# %% [markdown] -\"\"\" -__Running tutorial__ -\"\"\" - -{tutorial_text[second_cell:]} -""", - "py:percent", - ) - - return inner +# installing dependencies +%pip install -q {matchobj.group(1)} +""" + + +class DocumentationLink(ReplacePattern): + """ + Replace documentation linking directives. + + Replace strings of the `%doclink({args})` format with corresponding links to local files. + + `args` is a comma-separated string of arguments to pass to the :py:meth:`.DocumentationLink.link_to_doc_page`. + + So, `%doclink(arg1,arg2,arg3)` will be replaced with `link_to_doc_page(arg1, arg2, arg3)`, and + `%doclink(arg1,arg2)` will be replaced with `link_to_doc_page(arg1, arg2)`. + + USAGE EXAMPLES + -------------- + + [link](%doclink(api,script.core.script)) + + [link](%doclink(api,script.core.script,Node)) + + [link](%doclink(tutorial,messengers.web_api_interface.4_streamlit_chat)) + + [link](%doclink(tutorial,messengers.web_api_interface.4_streamlit_chat,API-configuration)) + + [link](%doclink(guide,basic_conceptions)) + + [link](%doclink(guide,basic_conceptions,example-conversational-chat-bot)) + + """ + + pattern: ClassVar[re.Pattern] = re.compile(r"%doclink\((.+?)\)") + + @staticmethod + def link_to_doc_page( + page_type: Literal["api", "tutorial", "guide"], + page: str, + anchor: Optional[str] = None, + ): + """ + Create a link to a documentation page. + + :param page_type: + Type of the documentation: + + - "api" -- API reference + - "tutorial" -- Tutorials + - "guide" -- User guides + + :param page: + Name of the page without the common prefix. + + So, to link to keywords, pass "script.core.keywords" as page (omitting the "dff" prefix). + + To link to the basic script tutorial, pass "script.core.1_basics" (without the "tutorials" prefix). + + To link to the basic concepts guide, pass "basic_conceptions". + :param anchor: + An anchor on the page. (optional) + + For the "api" type, use only the last part of the linked object. + + So, to link to the `CLIMessengerInterface` class, pass "CLIMessengerInterface" only. + + To link to a specific section of a tutorial or a guide, pass an anchor as-is (e.g. "introduction"). + :return: + A link to the corresponding documentation part. + """ + if page_type == "api": + return f"../apiref/dff.{page}.rst" + (f"#dff.{page}.{anchor}" if anchor is not None else "") + elif page_type == "tutorial": + return f"../tutorials/tutorials.{page}.py" + (f"#{anchor}" if anchor is not None else "") + elif page_type == "guide": + return f"../user_guides/{page}.rst" + (f"#{anchor}" if anchor is not None else "") + + @staticmethod + def replacement_string(matchobj: re.Match) -> str: + args = matchobj.group(1).split(",") + return DocumentationLink.link_to_doc_page(*args) + + +def apply_replace_patterns(text: str) -> str: + for cls in (InstallationCell, DocumentationLink): + text = cls.replace(text) + + return text + + +def py_percent_to_notebook(text: str): + if jupytext is None: + raise ModuleNotFoundError("`doc` dependencies are not installed.") + return jupytext.reads(apply_replace_patterns(text), "py:percent") diff --git a/pytest.ini b/pytest.ini index cdd69f843..fdb92a986 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,5 +2,6 @@ markers = docker: marks tests as requiring docker containers to work telegram: marks tests as requiring telegram client API token to work + slow: marks tests as slow (taking more than a minute to complete) all: reserved by allow-skip none: reserved by allow-skip diff --git a/setup.py b/setup.py index ad9e6b27d..d00ee7fa8 100644 --- a/setup.py +++ b/setup.py @@ -100,26 +100,31 @@ def merge_req_lists(*req_lists: List[str]) -> List[str]: "pytest==7.4.0", "pytest-cov==4.1.0", "pytest-asyncio==0.21.0", + "pytest_virtualenv==1.7.0", "flake8==6.1.0", "click==8.1.3", "black==23.7.0", "isort==5.12.0", - "flask[async]==2.3.2", - "psutil==5.9.5", - "telethon==1.29.1", - "fastapi==0.101.0", - "uvicorn==0.23.1", - "websockets==11.0.2", - "locust==2.16.1", - "streamlit==1.25.0", - "streamlit-chat==0.1.1", ], requests_requirements, ) +tutorial_dependencies = [ + "flask[async]==2.3.2", + "psutil==5.9.5", + "telethon==1.29.1", + "fastapi==0.101.0", + "uvicorn==0.23.1", + "websockets==11.0.2", + "locust==2.16.1", + "streamlit==1.25.0", + "streamlit-chat==0.1.1", +] + tests_full = merge_req_lists( full, test_requirements, + tutorial_dependencies, ) doc = merge_req_lists( @@ -171,7 +176,6 @@ def merge_req_lists(*req_lists: List[str]) -> List[str]: "full": full, # full dependencies including all options above "tests": test_requirements, # dependencies for running tests "test_full": tests_full, # full dependencies for running all tests (all options above) - "tutorials": tests_full, # dependencies for running tutorials (all options above) "devel": devel, # dependencies for development "doc": doc, # dependencies for documentation "devel_full": devel_full, # full dependencies for development (all options above) diff --git a/tests/pipeline/test_tutorials.py b/tests/pipeline/test_tutorials.py index f48c2a4e8..422999240 100644 --- a/tests/pipeline/test_tutorials.py +++ b/tests/pipeline/test_tutorials.py @@ -26,7 +26,10 @@ ], ) def test_tutorials(tutorial_module_name: str): - tutorial_module = importlib.import_module(f"tutorials.{dot_path_to_addon}.{tutorial_module_name}") + try: + tutorial_module = importlib.import_module(f"tutorials.{dot_path_to_addon}.{tutorial_module_name}") + except ModuleNotFoundError as e: + pytest.skip(f"dependencies unavailable: {e.msg}") if tutorial_module_name == "6_custom_messenger_interface": happy_path = tuple( (req, Message(misc={"webpage": tutorial_module.construct_webpage_by_response(res.text)})) diff --git a/tests/tutorials/test_tutorials.py b/tests/tutorials/test_tutorials.py new file mode 100644 index 000000000..d21ad1b6f --- /dev/null +++ b/tests/tutorials/test_tutorials.py @@ -0,0 +1,49 @@ +from typing import TYPE_CHECKING +import re +from pathlib import Path + +import pytest + +if TYPE_CHECKING: + from pytest_virtualenv import VirtualEnv + +from docs.source.utils.notebook import InstallationCell + + +PROJECT_ROOT_DIR = Path(__file__).parent.parent.parent +DFF_TUTORIAL_PY_FILES = map(str, (PROJECT_ROOT_DIR / "tutorials").glob("./**/*.py")) + + +def check_tutorial_dependencies(venv: "VirtualEnv", tutorial_source_code: str): + """ + Install dependencies required by a tutorial in `venv` and run the tutorial. + + :param venv: Virtual environment to run the tutorial in. + :param tutorial_source_code: Source code of the tutorial (unmodified by `apply_replace_patterns`). + :param tmp_path: Temporary path to save the tutorial to. + :return: + """ + tutorial_path = venv.workspace / "tutorial.py" + + venv.env["DISABLE_INTERACTIVE_MODE"] = "1" + + with open(tutorial_path, "w") as fd: + fd.write(tutorial_source_code) + + for deps in re.findall(InstallationCell.pattern, tutorial_source_code): + venv.run(f"python -m pip install {deps}", check_rc=True) + + venv.run(f"python {tutorial_path}", check_rc=True) + + +@pytest.mark.parametrize("dff_tutorial_py_file", DFF_TUTORIAL_PY_FILES) +@pytest.mark.slow +@pytest.mark.docker +def test_tutorials(dff_tutorial_py_file, virtualenv): + with open(dff_tutorial_py_file, "r", encoding="utf-8") as fd: + source_code = fd.read() + + check_tutorial_dependencies( + virtualenv, + source_code, + ) diff --git a/tutorials/context_storages/1_basics.py b/tutorials/context_storages/1_basics.py index c688586af..5a009a30f 100644 --- a/tutorials/context_storages/1_basics.py +++ b/tutorials/context_storages/1_basics.py @@ -5,6 +5,7 @@ The following tutorial shows the basic use of the database connection. """ +# %pip install dff[json,pickle] # %% import pathlib diff --git a/tutorials/context_storages/2_postgresql.py b/tutorials/context_storages/2_postgresql.py index 09aa949cf..b191c99b6 100644 --- a/tutorials/context_storages/2_postgresql.py +++ b/tutorials/context_storages/2_postgresql.py @@ -5,6 +5,7 @@ This is a tutorial on using PostgreSQL. """ +# %pip install dff[postgresql] # %% import os diff --git a/tutorials/context_storages/3_mongodb.py b/tutorials/context_storages/3_mongodb.py index a6ff2ec9d..449502a4d 100644 --- a/tutorials/context_storages/3_mongodb.py +++ b/tutorials/context_storages/3_mongodb.py @@ -5,6 +5,7 @@ This is a tutorial on using MongoDB. """ +# %pip install dff[mongodb] # %% import os diff --git a/tutorials/context_storages/4_redis.py b/tutorials/context_storages/4_redis.py index 28d6ba816..29c1df613 100644 --- a/tutorials/context_storages/4_redis.py +++ b/tutorials/context_storages/4_redis.py @@ -5,6 +5,7 @@ This is a tutorial on using Redis. """ +# %pip install dff[redis] # %% import os diff --git a/tutorials/context_storages/5_mysql.py b/tutorials/context_storages/5_mysql.py index b1f8e8a54..4f2cd885f 100644 --- a/tutorials/context_storages/5_mysql.py +++ b/tutorials/context_storages/5_mysql.py @@ -5,6 +5,7 @@ This is a tutorial on using MySQL. """ +# %pip install dff[mysql] # %% import os diff --git a/tutorials/context_storages/6_sqlite.py b/tutorials/context_storages/6_sqlite.py index ccc472b99..995ef4c3b 100644 --- a/tutorials/context_storages/6_sqlite.py +++ b/tutorials/context_storages/6_sqlite.py @@ -5,6 +5,7 @@ This is a tutorial on using SQLite. """ +# %pip install dff[sqlite] # %% import pathlib diff --git a/tutorials/context_storages/7_yandex_database.py b/tutorials/context_storages/7_yandex_database.py index 2a32f724c..865a9d2e1 100644 --- a/tutorials/context_storages/7_yandex_database.py +++ b/tutorials/context_storages/7_yandex_database.py @@ -5,6 +5,7 @@ This is a tutorial on how to use Yandex DataBase. """ +# %pip install dff[ydb] # %% import os diff --git a/tutorials/messengers/telegram/1_basic.py b/tutorials/messengers/telegram/1_basic.py index db3c07c41..91758d7b0 100644 --- a/tutorials/messengers/telegram/1_basic.py +++ b/tutorials/messengers/telegram/1_basic.py @@ -6,6 +6,7 @@ It asks users for the '/start' command and then loops in one place. """ +# %pip install dff[telegram] # %% import os diff --git a/tutorials/messengers/telegram/2_buttons.py b/tutorials/messengers/telegram/2_buttons.py index 2d536dbe3..0443aa0e6 100644 --- a/tutorials/messengers/telegram/2_buttons.py +++ b/tutorials/messengers/telegram/2_buttons.py @@ -6,6 +6,8 @@ This tutorial shows how to display and hide a basic keyboard in Telegram. """ +# %pip install dff[telegram] + # %% import os diff --git a/tutorials/messengers/telegram/3_buttons_with_callback.py b/tutorials/messengers/telegram/3_buttons_with_callback.py index d3a469a2d..cf457a4a8 100644 --- a/tutorials/messengers/telegram/3_buttons_with_callback.py +++ b/tutorials/messengers/telegram/3_buttons_with_callback.py @@ -7,6 +7,8 @@ inline queries. """ +# %pip install dff[telegram] + # %% import os diff --git a/tutorials/messengers/telegram/4_conditions.py b/tutorials/messengers/telegram/4_conditions.py index f6546ef47..95e251648 100644 --- a/tutorials/messengers/telegram/4_conditions.py +++ b/tutorials/messengers/telegram/4_conditions.py @@ -6,6 +6,8 @@ and reuse handler triggers from the `pytelegrambotapi` library. """ +# %pip install dff[telegram] + # %% import os diff --git a/tutorials/messengers/telegram/5_conditions_with_media.py b/tutorials/messengers/telegram/5_conditions_with_media.py index 06c8d68fc..e5e6dfe0c 100644 --- a/tutorials/messengers/telegram/5_conditions_with_media.py +++ b/tutorials/messengers/telegram/5_conditions_with_media.py @@ -5,6 +5,8 @@ This tutorial shows how to use media-related logic in your script. """ +# %pip install dff[telegram] + # %% import os diff --git a/tutorials/messengers/telegram/6_conditions_extras.py b/tutorials/messengers/telegram/6_conditions_extras.py index 1131d29b6..f86215aef 100644 --- a/tutorials/messengers/telegram/6_conditions_extras.py +++ b/tutorials/messengers/telegram/6_conditions_extras.py @@ -6,6 +6,8 @@ inherited from the `pytelegrambotapi` library. """ +# %pip install dff[telegram] + # %% import os diff --git a/tutorials/messengers/telegram/7_polling_setup.py b/tutorials/messengers/telegram/7_polling_setup.py index 5496cebf6..7c2ab2d6d 100644 --- a/tutorials/messengers/telegram/7_polling_setup.py +++ b/tutorials/messengers/telegram/7_polling_setup.py @@ -6,6 +6,7 @@ """ +# %pip install dff[telegram] # %% import os diff --git a/tutorials/messengers/telegram/8_webhook_setup.py b/tutorials/messengers/telegram/8_webhook_setup.py index 7f65fced9..4ebc62a6a 100644 --- a/tutorials/messengers/telegram/8_webhook_setup.py +++ b/tutorials/messengers/telegram/8_webhook_setup.py @@ -6,6 +6,7 @@ that makes your bot accessible through a public webhook. """ +# %pip install dff[telegram] flask # %% import os diff --git a/tutorials/messengers/web_api_interface/1_fastapi.py b/tutorials/messengers/web_api_interface/1_fastapi.py index f3672be68..77ca50c62 100644 --- a/tutorials/messengers/web_api_interface/1_fastapi.py +++ b/tutorials/messengers/web_api_interface/1_fastapi.py @@ -7,6 +7,7 @@ You can see the result at http://127.0.0.1:8000/docs. """ +# %pip install dff uvicorn fastapi # %% from dff.script import Message diff --git a/tutorials/messengers/web_api_interface/2_websocket_chat.py b/tutorials/messengers/web_api_interface/2_websocket_chat.py index dd8010e9e..40efce5f5 100644 --- a/tutorials/messengers/web_api_interface/2_websocket_chat.py +++ b/tutorials/messengers/web_api_interface/2_websocket_chat.py @@ -16,6 +16,7 @@ > This, of course, is not optimal and you wouldn't use it for production. """ +# %pip install dff uvicorn fastapi # %% from dff.script import Message diff --git a/tutorials/messengers/web_api_interface/3_load_testing_with_locust.py b/tutorials/messengers/web_api_interface/3_load_testing_with_locust.py index 57c9b18ea..f986187a4 100644 --- a/tutorials/messengers/web_api_interface/3_load_testing_with_locust.py +++ b/tutorials/messengers/web_api_interface/3_load_testing_with_locust.py @@ -5,6 +5,7 @@ This tutorial shows how to use an API endpoint created in the FastAPI tutorial in load testing. """ +# %pip install dff locust # %% [markdown] """ diff --git a/tutorials/messengers/web_api_interface/4_streamlit_chat.py b/tutorials/messengers/web_api_interface/4_streamlit_chat.py index ae46f6e39..6a64df2a1 100644 --- a/tutorials/messengers/web_api_interface/4_streamlit_chat.py +++ b/tutorials/messengers/web_api_interface/4_streamlit_chat.py @@ -7,6 +7,7 @@ # A demonstration of the chat: # ![demo](https://user-images.githubusercontent.com/61429541/238721597-ef88261d-e9e6-497d-ba68-0bcc9a765808.png) +# %pip install dff streamlit streamlit-chat # %% [markdown] # ## Running Streamlit: diff --git a/tutorials/pipeline/1_basics.py b/tutorials/pipeline/1_basics.py index e72e03d18..74257fa74 100644 --- a/tutorials/pipeline/1_basics.py +++ b/tutorials/pipeline/1_basics.py @@ -6,6 +6,7 @@ module as an extension to `dff.script.core`. """ +# %pip install dff # %% from dff.script import Context, Message diff --git a/tutorials/pipeline/2_pre_and_post_processors.py b/tutorials/pipeline/2_pre_and_post_processors.py index b021b65e6..b467395ce 100644 --- a/tutorials/pipeline/2_pre_and_post_processors.py +++ b/tutorials/pipeline/2_pre_and_post_processors.py @@ -6,6 +6,7 @@ module as an extension to `dff.script.core`. """ +# %pip install dff # %% import logging diff --git a/tutorials/pipeline/3_pipeline_dict_with_services_basic.py b/tutorials/pipeline/3_pipeline_dict_with_services_basic.py index 8b6ad9b2c..7f3c44cc6 100644 --- a/tutorials/pipeline/3_pipeline_dict_with_services_basic.py +++ b/tutorials/pipeline/3_pipeline_dict_with_services_basic.py @@ -6,6 +6,7 @@ dict and most important pipeline components. """ +# %pip install dff # %% import logging diff --git a/tutorials/pipeline/3_pipeline_dict_with_services_full.py b/tutorials/pipeline/3_pipeline_dict_with_services_full.py index e87b5db9f..950f37929 100644 --- a/tutorials/pipeline/3_pipeline_dict_with_services_full.py +++ b/tutorials/pipeline/3_pipeline_dict_with_services_full.py @@ -6,6 +6,7 @@ and most important pipeline components. """ +# %pip install dff # %% import json diff --git a/tutorials/pipeline/4_groups_and_conditions_basic.py b/tutorials/pipeline/4_groups_and_conditions_basic.py index 4ef8cb6ae..b833d5f12 100644 --- a/tutorials/pipeline/4_groups_and_conditions_basic.py +++ b/tutorials/pipeline/4_groups_and_conditions_basic.py @@ -5,6 +5,7 @@ The following example shows `pipeline` service group usage and start conditions. """ +# %pip install dff # %% import json diff --git a/tutorials/pipeline/4_groups_and_conditions_full.py b/tutorials/pipeline/4_groups_and_conditions_full.py index 585471bdd..112025268 100644 --- a/tutorials/pipeline/4_groups_and_conditions_full.py +++ b/tutorials/pipeline/4_groups_and_conditions_full.py @@ -5,6 +5,7 @@ The following tutorial shows `pipeline` service group usage and start conditions. """ +# %pip install dff # %% import logging diff --git a/tutorials/pipeline/5_asynchronous_groups_and_services_basic.py b/tutorials/pipeline/5_asynchronous_groups_and_services_basic.py index 4fb494b33..ddfcbf5ab 100644 --- a/tutorials/pipeline/5_asynchronous_groups_and_services_basic.py +++ b/tutorials/pipeline/5_asynchronous_groups_and_services_basic.py @@ -6,6 +6,7 @@ service and service group usage. """ +# %pip install dff # %% import asyncio diff --git a/tutorials/pipeline/5_asynchronous_groups_and_services_full.py b/tutorials/pipeline/5_asynchronous_groups_and_services_full.py index 970abecb1..7141ba220 100644 --- a/tutorials/pipeline/5_asynchronous_groups_and_services_full.py +++ b/tutorials/pipeline/5_asynchronous_groups_and_services_full.py @@ -6,6 +6,7 @@ asynchronous service and service group usage. """ +# %pip install dff # %% import asyncio diff --git a/tutorials/pipeline/6_custom_messenger_interface.py b/tutorials/pipeline/6_custom_messenger_interface.py index 9ace91e29..19a704e54 100644 --- a/tutorials/pipeline/6_custom_messenger_interface.py +++ b/tutorials/pipeline/6_custom_messenger_interface.py @@ -5,6 +5,7 @@ The following tutorial shows messenger interfaces usage. """ +# %pip install dff flask # %% import logging diff --git a/tutorials/pipeline/7_extra_handlers_basic.py b/tutorials/pipeline/7_extra_handlers_basic.py index e9417979d..5e7186078 100644 --- a/tutorials/pipeline/7_extra_handlers_basic.py +++ b/tutorials/pipeline/7_extra_handlers_basic.py @@ -5,6 +5,7 @@ The following tutorial shows extra handlers possibilities and use cases. """ +# %pip install dff # %% import asyncio diff --git a/tutorials/pipeline/7_extra_handlers_full.py b/tutorials/pipeline/7_extra_handlers_full.py index f01a7c5b4..281f0801b 100644 --- a/tutorials/pipeline/7_extra_handlers_full.py +++ b/tutorials/pipeline/7_extra_handlers_full.py @@ -5,6 +5,7 @@ The following tutorial shows extra handlers possibilities and use cases. """ +# %pip install dff psutil # %% import json diff --git a/tutorials/pipeline/8_extra_handlers_and_extensions.py b/tutorials/pipeline/8_extra_handlers_and_extensions.py index f08902b2f..9828e4d84 100644 --- a/tutorials/pipeline/8_extra_handlers_and_extensions.py +++ b/tutorials/pipeline/8_extra_handlers_and_extensions.py @@ -6,6 +6,7 @@ by global extra handlers and custom functions. """ +# %pip install dff # %% import asyncio diff --git a/tutorials/script/core/1_basics.py b/tutorials/script/core/1_basics.py index 968c1f599..b8a3606ac 100644 --- a/tutorials/script/core/1_basics.py +++ b/tutorials/script/core/1_basics.py @@ -6,6 +6,7 @@ Let's do all the necessary imports from DFF: """ +# %pip install dff # %% from dff.script import TRANSITIONS, RESPONSE, Message diff --git a/tutorials/script/core/2_conditions.py b/tutorials/script/core/2_conditions.py index 6ff1d5ed5..1b0ac3030 100644 --- a/tutorials/script/core/2_conditions.py +++ b/tutorials/script/core/2_conditions.py @@ -7,6 +7,7 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff # %% import re diff --git a/tutorials/script/core/3_responses.py b/tutorials/script/core/3_responses.py index 62112701b..bc6f0c92d 100644 --- a/tutorials/script/core/3_responses.py +++ b/tutorials/script/core/3_responses.py @@ -6,6 +6,7 @@ Let's do all the necessary imports from DFF. """ +# %pip install dff # %% import re diff --git a/tutorials/script/core/4_transitions.py b/tutorials/script/core/4_transitions.py index 6de30f6f4..eaaf9de89 100644 --- a/tutorials/script/core/4_transitions.py +++ b/tutorials/script/core/4_transitions.py @@ -6,6 +6,8 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff + # %% import re diff --git a/tutorials/script/core/5_global_transitions.py b/tutorials/script/core/5_global_transitions.py index c26b9d301..8fc51e270 100644 --- a/tutorials/script/core/5_global_transitions.py +++ b/tutorials/script/core/5_global_transitions.py @@ -6,6 +6,8 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff + # %% import re diff --git a/tutorials/script/core/6_context_serialization.py b/tutorials/script/core/6_context_serialization.py index 9c9f36539..bcf6cb7e2 100644 --- a/tutorials/script/core/6_context_serialization.py +++ b/tutorials/script/core/6_context_serialization.py @@ -6,6 +6,7 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff # %% import logging diff --git a/tutorials/script/core/7_pre_response_processing.py b/tutorials/script/core/7_pre_response_processing.py index 5b498a7bf..324509181 100644 --- a/tutorials/script/core/7_pre_response_processing.py +++ b/tutorials/script/core/7_pre_response_processing.py @@ -6,6 +6,7 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff # %% from dff.script import ( diff --git a/tutorials/script/core/8_misc.py b/tutorials/script/core/8_misc.py index 73e423460..b389d81d1 100644 --- a/tutorials/script/core/8_misc.py +++ b/tutorials/script/core/8_misc.py @@ -6,6 +6,7 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff # %% from dff.script import ( diff --git a/tutorials/script/core/9_pre_transitions_processing.py b/tutorials/script/core/9_pre_transitions_processing.py index a16bfcaeb..138775673 100644 --- a/tutorials/script/core/9_pre_transitions_processing.py +++ b/tutorials/script/core/9_pre_transitions_processing.py @@ -6,6 +6,7 @@ First of all, let's do all the necessary imports from DFF. """ +# %pip install dff # %% from dff.script import ( diff --git a/tutorials/script/responses/1_basics.py b/tutorials/script/responses/1_basics.py index d4307a8d2..138be697a 100644 --- a/tutorials/script/responses/1_basics.py +++ b/tutorials/script/responses/1_basics.py @@ -4,6 +4,7 @@ """ +# %pip install dff # %% from typing import NamedTuple diff --git a/tutorials/script/responses/2_buttons.py b/tutorials/script/responses/2_buttons.py index ae6f17dc4..88e81dec3 100644 --- a/tutorials/script/responses/2_buttons.py +++ b/tutorials/script/responses/2_buttons.py @@ -4,6 +4,8 @@ """ +# %pip install dff + # %% import dff.script.conditions as cnd import dff.script.labels as lbl diff --git a/tutorials/script/responses/3_media.py b/tutorials/script/responses/3_media.py index a27512dee..fb97d9803 100644 --- a/tutorials/script/responses/3_media.py +++ b/tutorials/script/responses/3_media.py @@ -4,6 +4,7 @@ """ +# %pip install dff # %% from dff.script import RESPONSE, TRANSITIONS diff --git a/tutorials/script/responses/4_multi_message.py b/tutorials/script/responses/4_multi_message.py index 6ddef9742..01fb0b968 100644 --- a/tutorials/script/responses/4_multi_message.py +++ b/tutorials/script/responses/4_multi_message.py @@ -6,6 +6,7 @@ Let's do all the necessary imports from DFF. """ +# %pip install dff # %% diff --git a/tutorials/utils/1_cache.py b/tutorials/utils/1_cache.py index 9c814e733..3de8aab5c 100644 --- a/tutorials/utils/1_cache.py +++ b/tutorials/utils/1_cache.py @@ -4,6 +4,7 @@ """ +# %pip install dff # %% from dff.script.conditions import true diff --git a/tutorials/utils/2_lru_cache.py b/tutorials/utils/2_lru_cache.py index 4e3f41c91..86d77289f 100644 --- a/tutorials/utils/2_lru_cache.py +++ b/tutorials/utils/2_lru_cache.py @@ -4,6 +4,8 @@ """ +# %pip install dff + # %% from dff.script.conditions import true from dff.script import Context, TRANSITIONS, RESPONSE, Message