diff --git a/docs/docs-beta/docs/guides/preview/components/existing-code-location.md b/docs/docs-beta/docs/guides/preview/components/existing-code-location.md index 31d5639d9e8f5..5fb4e81b8aa74 100644 --- a/docs/docs-beta/docs/guides/preview/components/existing-code-location.md +++ b/docs/docs-beta/docs/guides/preview/components/existing-code-location.md @@ -7,13 +7,50 @@ sidebar_position: 300 This guide is only relevant if you are starting from an _existing_ Dagster code location. This setup is unnecessary if you used `dg code-location generate` to create your code location. ::: -## Create a `components` directory +Let's begin with a Dagster code location that has some assets, but no components: -First, you'll want to create a directory to contain any new components you add to your code location. By convention, this directory is named `components`, and exists at the top level of your code location's Python module. + -```bash -mkdir components -``` +## Install dependencies + +### Install the `dg` command line tool + +We'll need to install the `dg` command line tool, which is used to scaffold components. We recommend installing `dg` globally using the [`uv`](https://docs.astral.sh/uv/getting-started/installation/) package manager; it can also be installed using `pip`. + + + +### Install `dagster-components` + +Next, we'll need to install the `dagster-components` package. + +Though this is optional, we generally recommend using a separate virtual environment for each code location, which can be accomplished using `uv`: + + + + + + Then, we can use `uv sync` to install the dependencies from our `pyproject.toml`, and then install the `dagster-components` package: + + + + + + + +## Update project structure + +### Update `pyproject.toml` + +Add a `tool.dg` section to your `pyproject.toml` file. This will tell the `dg` command line tool that this code location is a valid Dagster code location. + + + + +### Create a `components` directory + +Next, you'll want to create a directory to contain any new components you add to your code location. By convention, this directory is named `components`, and exists at the top level of your code location's Python module. + + ## Modify top-level definitions @@ -25,14 +62,16 @@ You can manually construct a set of definitions for your components using `build - + - + +Now, your code location is ready to use components! `dg` can be used to scaffold new components directly into the existing code location. + ## Next steps -- Add a new component to your code location -- Create a new component type +- [Add a new component to your code location](./using-a-component) +- [Create a new component type](./creating-a-component) diff --git a/docs/docs-beta/src/code-examples-content.js b/docs/docs-beta/src/code-examples-content.js index 32d199e3bc4fc..9cff3882e00aa 100644 --- a/docs/docs-beta/src/code-examples-content.js +++ b/docs/docs-beta/src/code-examples-content.js @@ -166,11 +166,10 @@ export const CODE_EXAMPLE_PATH_MAPPINGS = { 'docs_snippets/docs_snippets/concepts/logging/python_logging_handler_config.yaml': () => import('!!raw-loader!/../../examples/docs_snippets/docs_snippets/concepts/logging/python_logging_handler_config.yaml'), 'docs_snippets/docs_snippets/concepts/logging/python_logging_file_output_config.yaml': () => import('!!raw-loader!/../../examples/docs_snippets/docs_snippets/concepts/logging/python_logging_file_output_config.yaml'), 'docs_snippets/docs_snippets/concepts/logging/file_output_pipeline.py': () => import('!!raw-loader!/../../examples/docs_snippets/docs_snippets/concepts/logging/file_output_pipeline.py'), - 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-global.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-global.py'), - 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-asset.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-asset.py'), - 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-op.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-op.py'), 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-asset.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-asset.py'), 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-op.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-op.py'), + 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-asset.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-asset.py'), + 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-op.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-job-op.py'), 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-job-asset.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-job-asset.py'), 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-job-op.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-tag-key-job-op.py'), 'docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-no-more-than-1-job.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/tbd/concurrency-no-more-than-1-job.py'), @@ -179,8 +178,13 @@ export const CODE_EXAMPLE_PATH_MAPPINGS = { 'docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/with-build-defs.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/with-build-defs.py'), 'docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/defining-resolvable-field.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/defining-resolvable-field.py'), 'docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/resolving-resolvable-field.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/shell-script-component/resolving-resolvable-field.py'), - 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-before.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-before.py'), - 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-after.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-after.py'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/1-tree.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/1-tree.txt'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/3-uv-venv.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/3-uv-venv.txt'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/4-uv-freeze.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/4-uv-freeze.txt'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/2-pyproject.toml': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/2-pyproject.toml'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/5-mkdir-components.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/5-mkdir-components.txt'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py'), + 'docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/7-updated-definitions.py': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/7-updated-definitions.py'), 'docs_beta_snippets/docs_beta_snippets/guides/components/index/1-help.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/index/1-help.txt'), 'docs_beta_snippets/docs_beta_snippets/guides/components/index/2-scaffold.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/index/2-scaffold.txt'), 'docs_beta_snippets/docs_beta_snippets/guides/components/index/3-tree.txt': () => import('!!raw-loader!/../../examples/docs_beta_snippets/docs_beta_snippets/guides/components/index/3-tree.txt'), diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/1-tree.txt b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/1-tree.txt new file mode 100644 index 0000000000000..51515eb8376f8 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/1-tree.txt @@ -0,0 +1,14 @@ +tree + +. +├── README.md +├── my_existing_project +│   ├── __init__.py +│   ├── assets.py +│   └── definitions.py +├── my_existing_project_tests +│   ├── __init__.py +│   └── test_assets.py +└── pyproject.toml + +3 directories, 7 files diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/2-pyproject.toml b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/2-pyproject.toml new file mode 100644 index 0000000000000..ad96e7cb3ba5e --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/2-pyproject.toml @@ -0,0 +1,8 @@ +... +[tool.dg] +is_code_location = true + +[tool.dagster] +module_name = "my_existing_project.definitions" +code_location_name = "my_existing_project" +... diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/3-uv-venv.txt b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/3-uv-venv.txt new file mode 100644 index 0000000000000..e431dd359771e --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/3-uv-venv.txt @@ -0,0 +1 @@ +uv venv diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/4-uv-freeze.txt b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/4-uv-freeze.txt new file mode 100644 index 0000000000000..46cd974720503 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/4-uv-freeze.txt @@ -0,0 +1 @@ +uv sync && uv add dagster-components diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/5-mkdir-components.txt b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/5-mkdir-components.txt new file mode 100644 index 0000000000000..026409f2c9cb2 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/5-mkdir-components.txt @@ -0,0 +1 @@ +mkdir my_existing_project/components diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py new file mode 100644 index 0000000000000..6084f8a3cabe9 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py @@ -0,0 +1,8 @@ +import dagster as dg +from my_existing_project import assets + +all_assets = dg.load_assets_from_modules([assets]) + +defs = dg.Definitions( + assets=all_assets, +) diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-after.py b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/7-updated-definitions.py similarity index 60% rename from examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-after.py rename to examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/7-updated-definitions.py index 032bd40096b70..98013d99cf5d3 100644 --- a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-after.py +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/7-updated-definitions.py @@ -1,10 +1,13 @@ from pathlib import Path import dagster_components as dg_components +from my_existing_project import assets import dagster as dg +all_assets = dg.load_assets_from_modules([assets]) + defs = dg.Definitions.merge( - dg.Definitions(assets=[]), + dg.Definitions(assets=all_assets), dg_components.build_component_defs(Path(__file__).parent / "components"), ) diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/8-dg-list-component-types.txt b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/8-dg-list-component-types.txt new file mode 100644 index 0000000000000..561d34ffad4bd --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/8-dg-list-component-types.txt @@ -0,0 +1,12 @@ +dg component-type list + +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Component Type ┃ Summary ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ +│ definitions@dagster_components │ Wraps an arbitrary set of │ +│ │ Dagster definitions. │ +│ pipes_subprocess_script_collection@dagster_components │ Assets that wrap Python │ +│ │ scripts executed with │ +│ │ Dagster's │ +│ │ PipesSubprocessClient. │ +└───────────────────────────────────────────────────────┴────────────────────────────────┘ diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-before.py b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-before.py deleted file mode 100644 index 4ef34fa32e646..0000000000000 --- a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/definitions-before.py +++ /dev/null @@ -1,3 +0,0 @@ -import dagster as dg - -defs = dg.Definitions(assets=[]) diff --git a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/pyproject.toml b/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/pyproject.toml deleted file mode 100644 index 275a5c158cb65..0000000000000 --- a/examples/docs_beta_snippets/docs_beta_snippets/guides/components/existing-project/pyproject.toml +++ /dev/null @@ -1,2 +0,0 @@ -[tool.dagster] -module_name = "definitions" \ No newline at end of file diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/README.md b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/README.md new file mode 100644 index 0000000000000..9511ddd28bfb6 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/README.md @@ -0,0 +1 @@ +Sample existing project for testing docs for the "Making an existing code location components-compatible" guide. diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/__init__.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/__init__.py new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/__init__.py @@ -0,0 +1 @@ + diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/assets.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/assets.py new file mode 100644 index 0000000000000..b749d4af3cff5 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/assets.py @@ -0,0 +1,6 @@ +from dagster import asset + + +@asset +def my_asset(): + pass diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/definitions.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/definitions.py new file mode 100644 index 0000000000000..6084f8a3cabe9 --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project/definitions.py @@ -0,0 +1,8 @@ +import dagster as dg +from my_existing_project import assets + +all_assets = dg.load_assets_from_modules([assets]) + +defs = dg.Definitions( + assets=all_assets, +) diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/__init__.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/__init__.py new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/__init__.py @@ -0,0 +1 @@ + diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/test_assets.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/test_assets.py new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/my_existing_project_tests/test_assets.py @@ -0,0 +1 @@ + diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/pyproject.toml b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/pyproject.toml new file mode 100644 index 0000000000000..6a33dfcc440aa --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/my-existing-project/pyproject.toml @@ -0,0 +1,26 @@ +[project] +name = "my_existing_project" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.9,<3.13" +dependencies = [ + "dagster", +] + +[project.optional-dependencies] +dev = [ + "dagster-webserver", + "pytest>8", +] + +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[tool.dagster] +module_name = "my_existing_project.definitions" +code_location_name = "my_existing_project" + +[tool.setuptools.packages.find] +exclude=["my_existing_project_tests"] diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs.py index de4318e06b427..c5b0326cba2f8 100644 --- a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs.py +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs.py @@ -58,7 +58,6 @@ def next_snip_no(): ), ): os.chdir(tempdir) - subprocess.check_call(["uv", "pip", "install", "dg"]) run_command_and_snippet_output( cmd="dg --help", diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_deployments.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_deployments.py index 6667890b8773b..d0280c8e2968e 100644 --- a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_deployments.py +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_deployments.py @@ -53,7 +53,6 @@ def next_snip_no(): ), ): os.chdir(tempdir) - subprocess.check_call(["uv", "pip", "install", "dg"]) # Scaffold deployment run_command_and_snippet_output( diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_existing_code_location.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_existing_code_location.py new file mode 100644 index 0000000000000..d9527d81c8c0c --- /dev/null +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/guides/components/test_components_docs_existing_code_location.py @@ -0,0 +1,156 @@ +import os +import re +import subprocess +from pathlib import Path +from tempfile import TemporaryDirectory + +from dagster._utils.env import environ +from docs_beta_snippets_tests.snippet_checks.guides.components.utils import ( + DAGSTER_ROOT, + EDITABLE_DIR, +) +from docs_beta_snippets_tests.snippet_checks.utils import ( + _run_command, + check_file, + compare_tree_output, + create_file, + re_ignore_after, + re_ignore_before, + run_command_and_snippet_output, +) + +COMPONENTS_SNIPPETS_DIR = ( + DAGSTER_ROOT + / "examples" + / "docs_beta_snippets" + / "docs_beta_snippets" + / "guides" + / "components" + / "existing-project" +) + +MY_EXISTING_PROJECT = Path(__file__).parent / "my-existing-project" + + +def test_components_docs_index(update_snippets: bool) -> None: + snip_no = 0 + + def next_snip_no(): + nonlocal snip_no + snip_no += 1 + return snip_no + + with ( + TemporaryDirectory() as tempdir, + ( + environ( + { + "COLUMNS": "90", + "NO_COLOR": "1", + "HOME": "/tmp", + "DAGSTER_GIT_REPO_DIR": str(DAGSTER_ROOT), + "VIRTUAL_ENV": "", + } + ) + ), + ): + # tempdir = Path("/tmp/test-components-docs-existing-code-location") + # tempdir.mkdir(parents=True, exist_ok=True) + os.chdir(tempdir) + + _run_command(f"cp -r {MY_EXISTING_PROJECT} . && cd my-existing-project") + _run_command(r"find . -type d -name __pycache__ -exec rm -r {} \+") + + run_command_and_snippet_output( + cmd="tree", + snippet_path=COMPONENTS_SNIPPETS_DIR / f"{next_snip_no()}-tree.txt", + update_snippets=update_snippets, + custom_comparison_fn=compare_tree_output, + ) + + # Add components section to pyproject.toml + pyproject_contents = Path("pyproject.toml").read_text() + tool_dg_section = """[tool.dg] +is_code_location = true +""" + pyproject_contents = pyproject_contents.replace( + "[tool.dagster]", f"{tool_dg_section}\n[tool.dagster]" + ) + Path("pyproject.toml").write_text(pyproject_contents) + + check_file( + "pyproject.toml", + snippet_path=COMPONENTS_SNIPPETS_DIR / f"{next_snip_no()}-pyproject.toml", + snippet_replace_regex=[ + re_ignore_before("[tool.dg]"), + re_ignore_after('code_location_name = "my_existing_project"'), + ], + update_snippets=update_snippets, + ) + + run_command_and_snippet_output( + cmd="uv venv", + snippet_path=COMPONENTS_SNIPPETS_DIR / f"{next_snip_no()}-uv-venv.txt", + update_snippets=update_snippets, + ignore_output=True, + ) + + run_command_and_snippet_output( + cmd="uv sync && uv add dagster-components", + snippet_path=COMPONENTS_SNIPPETS_DIR / f"{next_snip_no()}-uv-freeze.txt", + update_snippets=update_snippets, + ignore_output=True, + ) + + _run_command( + f"uv add --editable '{EDITABLE_DIR / 'dagster-components'!s}' '{DAGSTER_ROOT / 'python_modules' / 'dagster'!s}' '{DAGSTER_ROOT / 'python_modules' / 'dagster-webserver'!s}'" + ) + _run_command( + "uv run dagster asset materialize --select '*' -m 'my_existing_project.definitions'" + ) + + run_command_and_snippet_output( + cmd="mkdir my_existing_project/components", + snippet_path=COMPONENTS_SNIPPETS_DIR + / f"{next_snip_no()}-mkdir-components.txt", + update_snippets=update_snippets, + ) + + check_file( + Path("my_existing_project") / "definitions.py", + snippet_path=COMPONENTS_SNIPPETS_DIR + / f"{next_snip_no()}-initial-definitions.py", + update_snippets=update_snippets, + ) + + # Update definitions.py to use components + create_file( + Path("my_existing_project") / "definitions.py", + contents="""from pathlib import Path + +import dagster_components as dg_components +from my_existing_project import assets + +import dagster as dg + +all_assets = dg.load_assets_from_modules([assets]) + +defs = dg.Definitions.merge( + dg.Definitions(assets=all_assets), + dg_components.build_component_defs(Path(__file__).parent / "components"), +) +""", + snippet_path=COMPONENTS_SNIPPETS_DIR + / f"{next_snip_no()}-updated-definitions.py", + ) + + _run_command( + "uv run dagster asset materialize --select '*' -m 'my_existing_project.definitions'" + ) + + run_command_and_snippet_output( + cmd="dg component-type list", + snippet_path=COMPONENTS_SNIPPETS_DIR + / f"{next_snip_no()}-dg-list-component-types.txt", + update_snippets=update_snippets, + ) diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/utils.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/utils.py index da46215599e62..e55651634e3de 100644 --- a/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/utils.py +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/snippet_checks/utils.py @@ -53,22 +53,25 @@ def _run_command( if not isinstance(cmd, str): cmd = " ".join(cmd) - actual_output = ( - subprocess.check_output( - f'{cmd}; echo "PWD=$(pwd);"', shell=True, stderr=subprocess.STDOUT + try: + actual_output = ( + subprocess.check_output( + f'{cmd} && echo "PWD=$(pwd);"', shell=True, stderr=subprocess.STDOUT + ) + .decode("utf-8") + .strip() ) - .decode("utf-8") - .strip() - ) + except subprocess.CalledProcessError as e: + print(f"Ran command {cmd}") # noqa: T201 + print("Got output:") # noqa: T201 + print(e.output.decode("utf-8").strip()) # noqa: T201 + raise pwd = PWD_REGEX.search(actual_output).group(1) actual_output = PWD_REGEX.sub("", actual_output) actual_output = ANSI_ESCAPE.sub("", actual_output) - print(f"Ran command {cmd}") # noqa: T201 - print("Got output:") # noqa: T201 - print(actual_output) # noqa: T201 os.chdir(pwd) return actual_output diff --git a/examples/docs_beta_snippets/docs_beta_snippets_tests/test_all_files_load.py b/examples/docs_beta_snippets/docs_beta_snippets_tests/test_all_files_load.py index 231a1f2379642..7f8c7af2a7827 100644 --- a/examples/docs_beta_snippets/docs_beta_snippets_tests/test_all_files_load.py +++ b/examples/docs_beta_snippets/docs_beta_snippets_tests/test_all_files_load.py @@ -24,6 +24,8 @@ f"{snippets_folder}/guides/components/existing-project/definitions-after.py", # there are no components defined in the snippets and so it would fail to load f"{snippets_folder}/guides/components/index/5-definitions.py", + f"{snippets_folder}/guides/components/existing-project/6-initial-definitions.py", + f"{snippets_folder}/guides/components/existing-project/7-updated-definitions.py", } EXCLUDED_DIRS = { diff --git a/examples/docs_beta_snippets/pyproject.toml b/examples/docs_beta_snippets/pyproject.toml index 1cac9a2823ffe..0b62b584d8440 100644 --- a/examples/docs_beta_snippets/pyproject.toml +++ b/examples/docs_beta_snippets/pyproject.toml @@ -6,6 +6,9 @@ extend = "../pyproject.toml" # Shorter line length for docs snippets for better browser formatting. line-length = 88 +# Ignore a specific file +extend-exclude = ["docs_beta_snippets/guides/components/existing-project/6-initial-definitions.py"] + [tool.ruff.lint] # Use extend-ignore so that we ignore all the same codes ignored in root.