mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-20 08:51:29 +00:00
Compare commits
5 Commits
enable-pos
...
dbeatty/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
434a59bf74 | ||
|
|
b290855443 | ||
|
|
64bfa152c2 | ||
|
|
9bb37ac986 | ||
|
|
9d80e597ce |
6
.changes/unreleased/Fixes-20240823-150343.yaml
Normal file
6
.changes/unreleased/Fixes-20240823-150343.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
kind: Fixes
|
||||||
|
body: Resolve relative local dependencies of local dependencies
|
||||||
|
time: 2024-08-23T15:03:43.292804-06:00
|
||||||
|
custom:
|
||||||
|
Author: dbeatty10
|
||||||
|
Issue: "10600"
|
||||||
@@ -56,6 +56,7 @@ class Package(dbtClassMixin):
|
|||||||
class LocalPackage(Package):
|
class LocalPackage(Package):
|
||||||
local: str
|
local: str
|
||||||
unrendered: Dict[str, Any] = field(default_factory=dict)
|
unrendered: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
project_root: Optional[str] = None
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class PinnedPackage(BasePackage):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def to_dict(self) -> Dict[str, str]:
|
def to_dict(self) -> Dict[str, Optional[str]]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def fetch_metadata(self, project, renderer):
|
def fetch_metadata(self, project, renderer):
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ class GitPinnedPackage(GitPackageMixin, PinnedPackage):
|
|||||||
self.subdirectory = subdirectory
|
self.subdirectory = subdirectory
|
||||||
self._checkout_name = md5sum(self.name)
|
self._checkout_name = md5sum(self.name)
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, str]:
|
def to_dict(self) -> Dict[str, Optional[str]]:
|
||||||
git_scrubbed = scrub_secrets(self.git_unrendered, env_secrets())
|
git_scrubbed = scrub_secrets(self.git_unrendered, env_secrets())
|
||||||
if self.git_unrendered != git_scrubbed:
|
if self.git_unrendered != git_scrubbed:
|
||||||
warn_or_error(DepsScrubbedPackageName(package_name=git_scrubbed))
|
warn_or_error(DepsScrubbedPackageName(package_name=git_scrubbed))
|
||||||
ret = {
|
ret: Dict[str, Optional[str]] = {
|
||||||
"git": git_scrubbed,
|
"git": git_scrubbed,
|
||||||
"revision": self.revision,
|
"revision": self.revision,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import shutil
|
import shutil
|
||||||
from typing import Dict
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from dbt.config.project import PartialProject, Project
|
from dbt.config.project import PartialProject, Project
|
||||||
from dbt.config.renderer import PackageRenderer
|
from dbt.config.renderer import PackageRenderer
|
||||||
@@ -11,9 +11,10 @@ from dbt_common.events.functions import fire_event
|
|||||||
|
|
||||||
|
|
||||||
class LocalPackageMixin:
|
class LocalPackageMixin:
|
||||||
def __init__(self, local: str) -> None:
|
def __init__(self, local: str, project_root: Optional[str] = None) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.local = local
|
self.local = local
|
||||||
|
self.project_root = project_root
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -24,12 +25,13 @@ class LocalPackageMixin:
|
|||||||
|
|
||||||
|
|
||||||
class LocalPinnedPackage(LocalPackageMixin, PinnedPackage):
|
class LocalPinnedPackage(LocalPackageMixin, PinnedPackage):
|
||||||
def __init__(self, local: str) -> None:
|
def __init__(self, local: str, project_root: Optional[str] = None) -> None:
|
||||||
super().__init__(local)
|
super().__init__(local, project_root)
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, str]:
|
def to_dict(self) -> Dict[str, Optional[str]]:
|
||||||
return {
|
return {
|
||||||
"local": self.local,
|
"local": self.local,
|
||||||
|
"project_root": self.project_root,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
@@ -38,10 +40,17 @@ class LocalPinnedPackage(LocalPackageMixin, PinnedPackage):
|
|||||||
def nice_version_name(self):
|
def nice_version_name(self):
|
||||||
return "<local @ {}>".format(self.local)
|
return "<local @ {}>".format(self.local)
|
||||||
|
|
||||||
def resolve_path(self, project):
|
def resolve_path(self, project: Project) -> str:
|
||||||
|
"""If `self.local` is a relative path, create an absolute path
|
||||||
|
with either `self.project_root` or `project.project_root` as the base.
|
||||||
|
|
||||||
|
If `self.local` is an absolute path or a user path (~), just
|
||||||
|
resolve it to an absolute path and return.
|
||||||
|
"""
|
||||||
|
|
||||||
return system.resolve_path_from_base(
|
return system.resolve_path_from_base(
|
||||||
self.local,
|
self.local,
|
||||||
project.project_root,
|
self.project_root if self.project_root else project.project_root,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _fetch_metadata(
|
def _fetch_metadata(
|
||||||
@@ -70,10 +79,10 @@ class LocalPinnedPackage(LocalPackageMixin, PinnedPackage):
|
|||||||
class LocalUnpinnedPackage(LocalPackageMixin, UnpinnedPackage[LocalPinnedPackage]):
|
class LocalUnpinnedPackage(LocalPackageMixin, UnpinnedPackage[LocalPinnedPackage]):
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_contract(cls, contract: LocalPackage) -> "LocalUnpinnedPackage":
|
def from_contract(cls, contract: LocalPackage) -> "LocalUnpinnedPackage":
|
||||||
return cls(local=contract.local)
|
return cls(local=contract.local, project_root=contract.project_root)
|
||||||
|
|
||||||
def incorporate(self, other: "LocalUnpinnedPackage") -> "LocalUnpinnedPackage":
|
def incorporate(self, other: "LocalUnpinnedPackage") -> "LocalUnpinnedPackage":
|
||||||
return LocalUnpinnedPackage(local=self.local)
|
return LocalUnpinnedPackage(local=other.local, project_root=other.project_root)
|
||||||
|
|
||||||
def resolved(self) -> LocalPinnedPackage:
|
def resolved(self) -> LocalPinnedPackage:
|
||||||
return LocalPinnedPackage(local=self.local)
|
return LocalPinnedPackage(local=self.local, project_root=self.project_root)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Dict, List
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from dbt.clients import registry
|
from dbt.clients import registry
|
||||||
from dbt.contracts.project import RegistryPackage, RegistryPackageMetadata
|
from dbt.contracts.project import RegistryPackage, RegistryPackageMetadata
|
||||||
@@ -37,7 +37,7 @@ class RegistryPinnedPackage(RegistryPackageMixin, PinnedPackage):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return self.package
|
return self.package
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, str]:
|
def to_dict(self) -> Dict[str, Optional[str]]:
|
||||||
return {
|
return {
|
||||||
"package": self.package,
|
"package": self.package,
|
||||||
"version": self.version,
|
"version": self.version,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Dict, Iterator, List, NoReturn, Set, Type
|
from typing import Any, Dict, Iterator, List, NoReturn, Optional, Set, Type
|
||||||
|
|
||||||
from dbt.config import Project
|
from dbt.config import Project
|
||||||
from dbt.config.renderer import PackageRenderer
|
from dbt.config.renderer import PackageRenderer
|
||||||
@@ -66,11 +66,13 @@ class PackageListing:
|
|||||||
else:
|
else:
|
||||||
self.packages[key] = package
|
self.packages[key] = package
|
||||||
|
|
||||||
def update_from(self, src: List[PackageSpec]) -> None:
|
def update_from(self, src: List[PackageSpec], project_root: Optional[str] = None) -> None:
|
||||||
pkg: UnpinnedPackage
|
pkg: UnpinnedPackage
|
||||||
for contract in src:
|
for contract in src:
|
||||||
if isinstance(contract, LocalPackage):
|
if isinstance(contract, LocalPackage):
|
||||||
pkg = LocalUnpinnedPackage.from_contract(contract)
|
pkg = LocalUnpinnedPackage.from_contract(contract)
|
||||||
|
# Override the project root for the local package contract IFF it is provided
|
||||||
|
pkg.project_root = project_root if project_root else pkg.project_root
|
||||||
elif isinstance(contract, TarballPackage):
|
elif isinstance(contract, TarballPackage):
|
||||||
pkg = TarballUnpinnedPackage.from_contract(contract)
|
pkg = TarballUnpinnedPackage.from_contract(contract)
|
||||||
elif isinstance(contract, GitPackage):
|
elif isinstance(contract, GitPackage):
|
||||||
@@ -86,9 +88,11 @@ class PackageListing:
|
|||||||
self.incorporate(pkg)
|
self.incorporate(pkg)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_contracts(cls: Type["PackageListing"], src: List[PackageSpec]) -> "PackageListing":
|
def from_contracts(
|
||||||
|
cls: Type["PackageListing"], src: List[PackageSpec], project_root: Optional[str] = None
|
||||||
|
) -> "PackageListing":
|
||||||
self = cls({})
|
self = cls({})
|
||||||
self.update_from(src)
|
self.update_from(src, project_root=project_root)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def resolved(self) -> List[PinnedPackage]:
|
def resolved(self) -> List[PinnedPackage]:
|
||||||
@@ -118,7 +122,7 @@ def resolve_packages(
|
|||||||
project: Project,
|
project: Project,
|
||||||
cli_vars: Dict[str, Any],
|
cli_vars: Dict[str, Any],
|
||||||
) -> List[PinnedPackage]:
|
) -> List[PinnedPackage]:
|
||||||
pending = PackageListing.from_contracts(packages)
|
pending = PackageListing.from_contracts(packages, project_root=project.project_root)
|
||||||
final = PackageListing()
|
final = PackageListing()
|
||||||
|
|
||||||
renderer = PackageRenderer(cli_vars)
|
renderer = PackageRenderer(cli_vars)
|
||||||
@@ -129,7 +133,14 @@ def resolve_packages(
|
|||||||
for package in pending:
|
for package in pending:
|
||||||
final.incorporate(package)
|
final.incorporate(package)
|
||||||
target = final[package].resolved().fetch_metadata(project, renderer)
|
target = final[package].resolved().fetch_metadata(project, renderer)
|
||||||
next_pending.update_from(target.packages)
|
|
||||||
|
# Hack to get the project root if it is a LocalPackage
|
||||||
|
# https://github.com/dbt-labs/dbt-core/issues/5410
|
||||||
|
project_root = None
|
||||||
|
if isinstance(package, LocalUnpinnedPackage):
|
||||||
|
project_root = package.resolved().resolve_path(project)
|
||||||
|
|
||||||
|
next_pending.update_from(target.packages, project_root=project_root)
|
||||||
pending = next_pending
|
pending = next_pending
|
||||||
|
|
||||||
resolved = final.resolved()
|
resolved = final.resolved()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from dbt.config.project import PartialProject
|
from dbt.config.project import PartialProject
|
||||||
from dbt.contracts.project import TarballPackage
|
from dbt.contracts.project import TarballPackage
|
||||||
@@ -39,7 +39,7 @@ class TarballPinnedPackage(TarballPackageMixin, PinnedPackage):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return self.package
|
return self.package
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, str]:
|
def to_dict(self) -> Dict[str, Optional[str]]:
|
||||||
tarball_scrubbed = scrub_secrets(self.tarball_unrendered, env_secrets())
|
tarball_scrubbed = scrub_secrets(self.tarball_unrendered, env_secrets())
|
||||||
if self.tarball_unrendered != tarball_scrubbed:
|
if self.tarball_unrendered != tarball_scrubbed:
|
||||||
warn_or_error(DepsScrubbedPackageName(package_name=tarball_scrubbed))
|
warn_or_error(DepsScrubbedPackageName(package_name=tarball_scrubbed))
|
||||||
|
|||||||
Reference in New Issue
Block a user