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.