We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix `KeyError: venv_name` and similar errors in lockfiles


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/meltano/core/plugin_lock_service.py`
Content:
```
1 """Plugin Lockfile Service."""
2 
3 from __future__ import annotations
4 
5 import json
6 from pathlib import Path
7 
8 from structlog.stdlib import get_logger
9 
10 from meltano.core.plugin.base import BasePlugin, PluginRef, StandalonePlugin, Variant
11 from meltano.core.project import Project
12 
13 logger = get_logger(__name__)
14 
15 
16 class LockfileAlreadyExistsError(Exception):
17     """Raised when a plugin lockfile already exists."""
18 
19     def __init__(self, message: str, path: Path, plugin: PluginRef):
20         """Create a new LockfileAlreadyExistsError.
21 
22         Args:
23             message: The error message.
24             path: The path to the existing lockfile.
25             plugin: The plugin that was locked.
26         """
27         self.path = path
28         self.plugin = plugin
29         super().__init__(message)
30 
31 
32 class PluginLockService:
33     """Plugin Lockfile Service."""
34 
35     def __init__(self, project: Project):
36         """Create a new Plugin Lockfile Service.
37 
38         Args:
39             project: The Meltano project.
40         """
41         self.project = project
42 
43     def save(
44         self,
45         plugin: BasePlugin,
46         *,
47         overwrite: bool = False,
48         exists_ok: bool = False,
49     ):
50         """Save the plugin lockfile.
51 
52         Args:
53             plugin: The plugin definition to save.
54             overwrite: Whether to overwrite the lockfile if it already exists.
55             exists_ok: Whether raise an exception if the lockfile already exists.
56 
57         Raises:
58             LockfileAlreadyExistsError: If the lockfile already exists and is not
59                 flagged for overwriting.
60         """
61         variant = None if plugin.variant == Variant.DEFAULT_NAME else plugin.variant
62 
63         logger.info(f"Locking a {type(plugin)}")
64 
65         plugin_def = plugin.definition
66         path = self.project.plugin_lock_path(
67             plugin_def.type,
68             plugin_def.name,
69             variant_name=variant,
70         )
71 
72         if path.exists() and not overwrite and not exists_ok:
73             raise LockfileAlreadyExistsError(
74                 f"Lockfile already exists: {path}",
75                 path,
76                 plugin,
77             )
78 
79         variant = plugin_def.find_variant(plugin.variant)
80         locked_def = StandalonePlugin.from_variant(
81             variant,
82             plugin.name,
83             plugin.namespace,
84             plugin.type,
85             label=plugin.label,
86         )
87 
88         with path.open("w") as lockfile:
89             json.dump(locked_def.canonical(), lockfile, indent=2)
90 
91         logger.debug("Locked plugin definition", path=path)
92
```

Path: `src/meltano/core/project_add_service.py`
Content:
```
1 """Add plugins to the project."""
2 
3 from __future__ import annotations
4 
5 import enum
6 
7 from .plugin import BasePlugin, PluginType, Variant
8 from .plugin.project_plugin import ProjectPlugin
9 from .project import Project
10 from .project_plugins_service import PluginAlreadyAddedException, ProjectPluginsService
11 
12 
13 class PluginAddedReason(str, enum.Enum):
14     """The reason why a plugin was added to the project."""
15 
16     #: The plugin was added by the user.
17     USER_REQUEST = "user_request"
18 
19     #: The plugin was added because it is related to another plugin.
20     RELATED = "related"
21 
22     #: The plugin was added because it is required by another plugin.
23     REQUIRED = "required"
24 
25 
26 class MissingPluginException(Exception):
27     """Raised when a plugin is not found."""
28 
29 
30 class ProjectAddService:
31     """Project Add Service."""
32 
33     def __init__(
34         self,
35         project: Project,
36         plugins_service: ProjectPluginsService = None,
37     ):
38         """Create a new Project Add Service.
39 
40         Args:
41             project: The project to add plugins to.
42             plugins_service: The project plugins service.
43         """
44         self.project = project
45         self.plugins_service = plugins_service or ProjectPluginsService(project)
46 
47     def add(
48         self,
49         plugin_type: PluginType,
50         plugin_name: str,
51         lock: bool = True,
52         **attrs,
53     ) -> ProjectPlugin:
54         """Add a new plugin to the project.
55 
56         Args:
57             plugin_type: The type of the plugin to add.
58             plugin_name (str): The name of the plugin to add.
59             lock: Whether to generate a lockfile for the plugin.
60             attrs: Additional attributes to add to the plugin.
61 
62         Returns:
63             The added plugin.
64         """
65         plugin = ProjectPlugin(
66             plugin_type, plugin_name, **attrs, default_variant=Variant.DEFAULT_NAME
67         )
68 
69         with self.plugins_service.disallow_discovery_yaml():
70             self.plugins_service.ensure_parent(plugin)
71 
72             # If we are inheriting from a base plugin definition,
73             # repeat the variant and pip_url in meltano.yml
74             parent = plugin.parent
75             if isinstance(parent, BasePlugin):
76                 plugin.variant = parent.variant
77                 plugin.pip_url = parent.pip_url
78 
79             added = self.add_plugin(plugin)
80 
81             if lock and not added.is_custom():
82                 self.plugins_service.lock_service.save(
83                     added.parent,
84                     exists_ok=plugin.inherit_from is not None,
85                 )
86 
87             return added
88 
89     def add_plugin(self, plugin: ProjectPlugin):
90         """Add a plugin to the project.
91 
92         Args:
93             plugin: The plugin to add.
94 
95         Returns:
96             The added plugin.
97         """
98         return self.plugins_service.add_to_file(plugin)
99 
100     def add_required(
101         self,
102         plugin: ProjectPlugin,
103         lock: bool = True,
104     ):
105         """Add all required plugins to the project.
106 
107         Args:
108             plugin: The plugin to get requirements from.
109             lock: Whether to generate a lockfile for the plugin.
110 
111         Returns:
112             The added plugins.
113         """
114         added_plugins = []
115         for plugin_type, plugins in plugin.all_requires.items():
116             for plugin_req in plugins:
117                 try:
118                     plugin = self.add(
119                         plugin_type,
120                         plugin_req.name,
121                         variant=plugin_req.variant,
122                         lock=lock,
123                     )
124                 except PluginAlreadyAddedException:
125                     continue
126 
127                 added_plugins.append(plugin)
128 
129         added_plugins_with_required = []
130         for added in added_plugins:
131             added_plugins_with_required.extend([added, *self.add_required(added)])
132 
133         return added_plugins_with_required
134
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/meltano/core/plugin_lock_service.py b/src/meltano/core/plugin_lock_service.py
--- a/src/meltano/core/plugin_lock_service.py
+++ b/src/meltano/core/plugin_lock_service.py
@@ -7,7 +7,8 @@
 
 from structlog.stdlib import get_logger
 
-from meltano.core.plugin.base import BasePlugin, PluginRef, StandalonePlugin, Variant
+from meltano.core.plugin.base import PluginRef, StandalonePlugin, Variant
+from meltano.core.plugin.project_plugin import ProjectPlugin
 from meltano.core.project import Project
 
 logger = get_logger(__name__)
@@ -42,7 +43,7 @@
 
     def save(
         self,
-        plugin: BasePlugin,
+        plugin: ProjectPlugin,
         *,
         overwrite: bool = False,
         exists_ok: bool = False,
@@ -58,11 +59,12 @@
             LockfileAlreadyExistsError: If the lockfile already exists and is not
                 flagged for overwriting.
         """
-        variant = None if plugin.variant == Variant.DEFAULT_NAME else plugin.variant
-
-        logger.info(f"Locking a {type(plugin)}")
+        base_plugin = plugin.parent
+        variant = (
+            None if base_plugin.variant == Variant.DEFAULT_NAME else base_plugin.variant
+        )
 
-        plugin_def = plugin.definition
+        plugin_def = base_plugin.definition
         path = self.project.plugin_lock_path(
             plugin_def.type,
             plugin_def.name,
@@ -76,13 +78,13 @@
                 plugin,
             )
 
-        variant = plugin_def.find_variant(plugin.variant)
+        variant = plugin_def.find_variant(base_plugin.variant)
         locked_def = StandalonePlugin.from_variant(
             variant,
-            plugin.name,
-            plugin.namespace,
-            plugin.type,
-            label=plugin.label,
+            base_plugin.name,
+            base_plugin.namespace,
+            base_plugin.type,
+            label=base_plugin.label,
         )
 
         with path.open("w") as lockfile:
diff --git a/src/meltano/core/project_add_service.py b/src/meltano/core/project_add_service.py
--- a/src/meltano/core/project_add_service.py
+++ b/src/meltano/core/project_add_service.py
@@ -80,7 +80,7 @@
 
             if lock and not added.is_custom():
                 self.plugins_service.lock_service.save(
-                    added.parent,
+                    added,
                     exists_ok=plugin.inherit_from is not None,
                 )

{"golden_diff": "diff --git a/src/meltano/core/plugin_lock_service.py b/src/meltano/core/plugin_lock_service.py\n--- a/src/meltano/core/plugin_lock_service.py\n+++ b/src/meltano/core/plugin_lock_service.py\n@@ -7,7 +7,8 @@\n \n from structlog.stdlib import get_logger\n \n-from meltano.core.plugin.base import BasePlugin, PluginRef, StandalonePlugin, Variant\n+from meltano.core.plugin.base import PluginRef, StandalonePlugin, Variant\n+from meltano.core.plugin.project_plugin import ProjectPlugin\n from meltano.core.project import Project\n \n logger = get_logger(__name__)\n@@ -42,7 +43,7 @@\n \n     def save(\n         self,\n-        plugin: BasePlugin,\n+        plugin: ProjectPlugin,\n         *,\n         overwrite: bool = False,\n         exists_ok: bool = False,\n@@ -58,11 +59,12 @@\n             LockfileAlreadyExistsError: If the lockfile already exists and is not\n                 flagged for overwriting.\n         \"\"\"\n-        variant = None if plugin.variant == Variant.DEFAULT_NAME else plugin.variant\n-\n-        logger.info(f\"Locking a {type(plugin)}\")\n+        base_plugin = plugin.parent\n+        variant = (\n+            None if base_plugin.variant == Variant.DEFAULT_NAME else base_plugin.variant\n+        )\n \n-        plugin_def = plugin.definition\n+        plugin_def = base_plugin.definition\n         path = self.project.plugin_lock_path(\n             plugin_def.type,\n             plugin_def.name,\n@@ -76,13 +78,13 @@\n                 plugin,\n             )\n \n-        variant = plugin_def.find_variant(plugin.variant)\n+        variant = plugin_def.find_variant(base_plugin.variant)\n         locked_def = StandalonePlugin.from_variant(\n             variant,\n-            plugin.name,\n-            plugin.namespace,\n-            plugin.type,\n-            label=plugin.label,\n+            base_plugin.name,\n+            base_plugin.namespace,\n+            base_plugin.type,\n+            label=base_plugin.label,\n         )\n \n         with path.open(\"w\") as lockfile:\ndiff --git a/src/meltano/core/project_add_service.py b/src/meltano/core/project_add_service.py\n--- a/src/meltano/core/project_add_service.py\n+++ b/src/meltano/core/project_add_service.py\n@@ -80,7 +80,7 @@\n \n             if lock and not added.is_custom():\n                 self.plugins_service.lock_service.save(\n-                    added.parent,\n+                    added,\n                     exists_ok=plugin.inherit_from is not None,\n                 )\n", "issue": "Fix `KeyError: venv_name` and similar errors in lockfiles\n\n", "before_files": [{"content": "\"\"\"Plugin Lockfile Service.\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nfrom pathlib import Path\n\nfrom structlog.stdlib import get_logger\n\nfrom meltano.core.plugin.base import BasePlugin, PluginRef, StandalonePlugin, Variant\nfrom meltano.core.project import Project\n\nlogger = get_logger(__name__)\n\n\nclass LockfileAlreadyExistsError(Exception):\n    \"\"\"Raised when a plugin lockfile already exists.\"\"\"\n\n    def __init__(self, message: str, path: Path, plugin: PluginRef):\n        \"\"\"Create a new LockfileAlreadyExistsError.\n\n        Args:\n            message: The error message.\n            path: The path to the existing lockfile.\n            plugin: The plugin that was locked.\n        \"\"\"\n        self.path = path\n        self.plugin = plugin\n        super().__init__(message)\n\n\nclass PluginLockService:\n    \"\"\"Plugin Lockfile Service.\"\"\"\n\n    def __init__(self, project: Project):\n        \"\"\"Create a new Plugin Lockfile Service.\n\n        Args:\n            project: The Meltano project.\n        \"\"\"\n        self.project = project\n\n    def save(\n        self,\n        plugin: BasePlugin,\n        *,\n        overwrite: bool = False,\n        exists_ok: bool = False,\n    ):\n        \"\"\"Save the plugin lockfile.\n\n        Args:\n            plugin: The plugin definition to save.\n            overwrite: Whether to overwrite the lockfile if it already exists.\n            exists_ok: Whether raise an exception if the lockfile already exists.\n\n        Raises:\n            LockfileAlreadyExistsError: If the lockfile already exists and is not\n                flagged for overwriting.\n        \"\"\"\n        variant = None if plugin.variant == Variant.DEFAULT_NAME else plugin.variant\n\n        logger.info(f\"Locking a {type(plugin)}\")\n\n        plugin_def = plugin.definition\n        path = self.project.plugin_lock_path(\n            plugin_def.type,\n            plugin_def.name,\n            variant_name=variant,\n        )\n\n        if path.exists() and not overwrite and not exists_ok:\n            raise LockfileAlreadyExistsError(\n                f\"Lockfile already exists: {path}\",\n                path,\n                plugin,\n            )\n\n        variant = plugin_def.find_variant(plugin.variant)\n        locked_def = StandalonePlugin.from_variant(\n            variant,\n            plugin.name,\n            plugin.namespace,\n            plugin.type,\n            label=plugin.label,\n        )\n\n        with path.open(\"w\") as lockfile:\n            json.dump(locked_def.canonical(), lockfile, indent=2)\n\n        logger.debug(\"Locked plugin definition\", path=path)\n", "path": "src/meltano/core/plugin_lock_service.py"}, {"content": "\"\"\"Add plugins to the project.\"\"\"\n\nfrom __future__ import annotations\n\nimport enum\n\nfrom .plugin import BasePlugin, PluginType, Variant\nfrom .plugin.project_plugin import ProjectPlugin\nfrom .project import Project\nfrom .project_plugins_service import PluginAlreadyAddedException, ProjectPluginsService\n\n\nclass PluginAddedReason(str, enum.Enum):\n    \"\"\"The reason why a plugin was added to the project.\"\"\"\n\n    #: The plugin was added by the user.\n    USER_REQUEST = \"user_request\"\n\n    #: The plugin was added because it is related to another plugin.\n    RELATED = \"related\"\n\n    #: The plugin was added because it is required by another plugin.\n    REQUIRED = \"required\"\n\n\nclass MissingPluginException(Exception):\n    \"\"\"Raised when a plugin is not found.\"\"\"\n\n\nclass ProjectAddService:\n    \"\"\"Project Add Service.\"\"\"\n\n    def __init__(\n        self,\n        project: Project,\n        plugins_service: ProjectPluginsService = None,\n    ):\n        \"\"\"Create a new Project Add Service.\n\n        Args:\n            project: The project to add plugins to.\n            plugins_service: The project plugins service.\n        \"\"\"\n        self.project = project\n        self.plugins_service = plugins_service or ProjectPluginsService(project)\n\n    def add(\n        self,\n        plugin_type: PluginType,\n        plugin_name: str,\n        lock: bool = True,\n        **attrs,\n    ) -> ProjectPlugin:\n        \"\"\"Add a new plugin to the project.\n\n        Args:\n            plugin_type: The type of the plugin to add.\n            plugin_name (str): The name of the plugin to add.\n            lock: Whether to generate a lockfile for the plugin.\n            attrs: Additional attributes to add to the plugin.\n\n        Returns:\n            The added plugin.\n        \"\"\"\n        plugin = ProjectPlugin(\n            plugin_type, plugin_name, **attrs, default_variant=Variant.DEFAULT_NAME\n        )\n\n        with self.plugins_service.disallow_discovery_yaml():\n            self.plugins_service.ensure_parent(plugin)\n\n            # If we are inheriting from a base plugin definition,\n            # repeat the variant and pip_url in meltano.yml\n            parent = plugin.parent\n            if isinstance(parent, BasePlugin):\n                plugin.variant = parent.variant\n                plugin.pip_url = parent.pip_url\n\n            added = self.add_plugin(plugin)\n\n            if lock and not added.is_custom():\n                self.plugins_service.lock_service.save(\n                    added.parent,\n                    exists_ok=plugin.inherit_from is not None,\n                )\n\n            return added\n\n    def add_plugin(self, plugin: ProjectPlugin):\n        \"\"\"Add a plugin to the project.\n\n        Args:\n            plugin: The plugin to add.\n\n        Returns:\n            The added plugin.\n        \"\"\"\n        return self.plugins_service.add_to_file(plugin)\n\n    def add_required(\n        self,\n        plugin: ProjectPlugin,\n        lock: bool = True,\n    ):\n        \"\"\"Add all required plugins to the project.\n\n        Args:\n            plugin: The plugin to get requirements from.\n            lock: Whether to generate a lockfile for the plugin.\n\n        Returns:\n            The added plugins.\n        \"\"\"\n        added_plugins = []\n        for plugin_type, plugins in plugin.all_requires.items():\n            for plugin_req in plugins:\n                try:\n                    plugin = self.add(\n                        plugin_type,\n                        plugin_req.name,\n                        variant=plugin_req.variant,\n                        lock=lock,\n                    )\n                except PluginAlreadyAddedException:\n                    continue\n\n                added_plugins.append(plugin)\n\n        added_plugins_with_required = []\n        for added in added_plugins:\n            added_plugins_with_required.extend([added, *self.add_required(added)])\n\n        return added_plugins_with_required\n", "path": "src/meltano/core/project_add_service.py"}], "after_files": [{"content": "\"\"\"Plugin Lockfile Service.\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nfrom pathlib import Path\n\nfrom structlog.stdlib import get_logger\n\nfrom meltano.core.plugin.base import PluginRef, StandalonePlugin, Variant\nfrom meltano.core.plugin.project_plugin import ProjectPlugin\nfrom meltano.core.project import Project\n\nlogger = get_logger(__name__)\n\n\nclass LockfileAlreadyExistsError(Exception):\n    \"\"\"Raised when a plugin lockfile already exists.\"\"\"\n\n    def __init__(self, message: str, path: Path, plugin: PluginRef):\n        \"\"\"Create a new LockfileAlreadyExistsError.\n\n        Args:\n            message: The error message.\n            path: The path to the existing lockfile.\n            plugin: The plugin that was locked.\n        \"\"\"\n        self.path = path\n        self.plugin = plugin\n        super().__init__(message)\n\n\nclass PluginLockService:\n    \"\"\"Plugin Lockfile Service.\"\"\"\n\n    def __init__(self, project: Project):\n        \"\"\"Create a new Plugin Lockfile Service.\n\n        Args:\n            project: The Meltano project.\n        \"\"\"\n        self.project = project\n\n    def save(\n        self,\n        plugin: ProjectPlugin,\n        *,\n        overwrite: bool = False,\n        exists_ok: bool = False,\n    ):\n        \"\"\"Save the plugin lockfile.\n\n        Args:\n            plugin: The plugin definition to save.\n            overwrite: Whether to overwrite the lockfile if it already exists.\n            exists_ok: Whether raise an exception if the lockfile already exists.\n\n        Raises:\n            LockfileAlreadyExistsError: If the lockfile already exists and is not\n                flagged for overwriting.\n        \"\"\"\n        base_plugin = plugin.parent\n        variant = (\n            None if base_plugin.variant == Variant.DEFAULT_NAME else base_plugin.variant\n        )\n\n        plugin_def = base_plugin.definition\n        path = self.project.plugin_lock_path(\n            plugin_def.type,\n            plugin_def.name,\n            variant_name=variant,\n        )\n\n        if path.exists() and not overwrite and not exists_ok:\n            raise LockfileAlreadyExistsError(\n                f\"Lockfile already exists: {path}\",\n                path,\n                plugin,\n            )\n\n        variant = plugin_def.find_variant(base_plugin.variant)\n        locked_def = StandalonePlugin.from_variant(\n            variant,\n            base_plugin.name,\n            base_plugin.namespace,\n            base_plugin.type,\n            label=base_plugin.label,\n        )\n\n        with path.open(\"w\") as lockfile:\n            json.dump(locked_def.canonical(), lockfile, indent=2)\n\n        logger.debug(\"Locked plugin definition\", path=path)\n", "path": "src/meltano/core/plugin_lock_service.py"}, {"content": "\"\"\"Add plugins to the project.\"\"\"\n\nfrom __future__ import annotations\n\nimport enum\n\nfrom .plugin import BasePlugin, PluginType, Variant\nfrom .plugin.project_plugin import ProjectPlugin\nfrom .project import Project\nfrom .project_plugins_service import PluginAlreadyAddedException, ProjectPluginsService\n\n\nclass PluginAddedReason(str, enum.Enum):\n    \"\"\"The reason why a plugin was added to the project.\"\"\"\n\n    #: The plugin was added by the user.\n    USER_REQUEST = \"user_request\"\n\n    #: The plugin was added because it is related to another plugin.\n    RELATED = \"related\"\n\n    #: The plugin was added because it is required by another plugin.\n    REQUIRED = \"required\"\n\n\nclass MissingPluginException(Exception):\n    \"\"\"Raised when a plugin is not found.\"\"\"\n\n\nclass ProjectAddService:\n    \"\"\"Project Add Service.\"\"\"\n\n    def __init__(\n        self,\n        project: Project,\n        plugins_service: ProjectPluginsService = None,\n    ):\n        \"\"\"Create a new Project Add Service.\n\n        Args:\n            project: The project to add plugins to.\n            plugins_service: The project plugins service.\n        \"\"\"\n        self.project = project\n        self.plugins_service = plugins_service or ProjectPluginsService(project)\n\n    def add(\n        self,\n        plugin_type: PluginType,\n        plugin_name: str,\n        lock: bool = True,\n        **attrs,\n    ) -> ProjectPlugin:\n        \"\"\"Add a new plugin to the project.\n\n        Args:\n            plugin_type: The type of the plugin to add.\n            plugin_name (str): The name of the plugin to add.\n            lock: Whether to generate a lockfile for the plugin.\n            attrs: Additional attributes to add to the plugin.\n\n        Returns:\n            The added plugin.\n        \"\"\"\n        plugin = ProjectPlugin(\n            plugin_type, plugin_name, **attrs, default_variant=Variant.DEFAULT_NAME\n        )\n\n        with self.plugins_service.disallow_discovery_yaml():\n            self.plugins_service.ensure_parent(plugin)\n\n            # If we are inheriting from a base plugin definition,\n            # repeat the variant and pip_url in meltano.yml\n            parent = plugin.parent\n            if isinstance(parent, BasePlugin):\n                plugin.variant = parent.variant\n                plugin.pip_url = parent.pip_url\n\n            added = self.add_plugin(plugin)\n\n            if lock and not added.is_custom():\n                self.plugins_service.lock_service.save(\n                    added,\n                    exists_ok=plugin.inherit_from is not None,\n                )\n\n            return added\n\n    def add_plugin(self, plugin: ProjectPlugin):\n        \"\"\"Add a plugin to the project.\n\n        Args:\n            plugin: The plugin to add.\n\n        Returns:\n            The added plugin.\n        \"\"\"\n        return self.plugins_service.add_to_file(plugin)\n\n    def add_required(\n        self,\n        plugin: ProjectPlugin,\n        lock: bool = True,\n    ):\n        \"\"\"Add all required plugins to the project.\n\n        Args:\n            plugin: The plugin to get requirements from.\n            lock: Whether to generate a lockfile for the plugin.\n\n        Returns:\n            The added plugins.\n        \"\"\"\n        added_plugins = []\n        for plugin_type, plugins in plugin.all_requires.items():\n            for plugin_req in plugins:\n                try:\n                    plugin = self.add(\n                        plugin_type,\n                        plugin_req.name,\n                        variant=plugin_req.variant,\n                        lock=lock,\n                    )\n                except PluginAlreadyAddedException:\n                    continue\n\n                added_plugins.append(plugin)\n\n        added_plugins_with_required = []\n        for added in added_plugins:\n            added_plugins_with_required.extend([added, *self.add_required(added)])\n\n        return added_plugins_with_required\n", "path": "src/meltano/core/project_add_service.py"}]}