Skip to content

Commit

Permalink
Attempt supporting multi-file version constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
knedlsepp committed Nov 10, 2023
1 parent c18d8f2 commit 8783024
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
109 changes: 109 additions & 0 deletions conda_lock/models/lock_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,132 @@ class _BaseDependency(StrictModel):
def sorted_extras(cls, v: List[str]) -> List[str]:
return sorted(v)

def merge(self, other):
if other is None:
return self
if (
self.name != other.name
or self.manager != other.manager
or self.category != other.category
):
raise ValueError(
"Cannot merge incompatible dependencies: {self} != {other}"
)
return _BaseDependency(
name=self.name,
manager=self.manager,
category=self.category,
extras=list(set(self.extras + other.extras)),
)


class VersionedDependency(_BaseDependency):
version: str
build: Optional[str] = None
conda_channel: Optional[str] = None

@staticmethod
def _merge_versions(version1, version2):
if version1 is None or version1 == "":
return version2
if version2 is None or version2 == "":
return version1
return f"{version1},{version2}"

def merge(self, other):
if other is None:
return self
if (
self.build is not None
and other.build is not None
and self.build != other.build
):
raise NotImplementedError(
f"VersionedDependency has two different builds:\n{self}\n{other}"
)

if (
self.conda_channel is not None
and other.conda_channel is not None
and self.conda_channel != other.conda_channel
):
raise NotImplementedError(
f"VersionedDependency has two different conda_channels:\n{self}\n{other}"
)
merged_base = super().merge(other)
return VersionedDependency(
name=merged_base.name,
manager=merged_base.manager,
category=merged_base.category,
extras=merged_base.extras,
version=self._merge_versions(self.version, other.version),
build=self.build or other.build,
conda_channel=self.conda_channel or other.conda_channel,
)


class URLDependency(_BaseDependency):
url: str
hashes: List[str]

def merge(self, other):
if other is None:
return self
if self.url != other.url:
raise NotImplementedError(
f"URLDependency has two different urls:\n{self}\n{other}"
)

if self.hashes != other.hashes:
raise NotImplementedError(
f"URLDependency has two different hashess:\n{self}\n{other}"
)
merged_base = super().merge(other)

return URLDependency(
name=merged_base.name,
manager=merged_base.manager,
category=merged_base.category,
extras=merged_base.extras,
url=self.url,
hashes=self.hashes,
)


class VCSDependency(_BaseDependency):
source: str
vcs: str
rev: Optional[str] = None

def merge(self, other):
if other is None:
return self
if self.source != other.source:
raise NotImplementedError(
f"VCSDependency has two different sources:\n{self}\n{other}"
)

if self.vcs != other.vcs:
raise NotImplementedError(
f"VCSDependency has two different vcss:\n{self}\n{other}"
)

if self.rev is not None and other.rev is not None and self.rev != other.rev:
raise NotImplementedError(
f"VCSDependency has two different revs:\n{self}\n{other}"
)
merged_base = super().merge(other)

return VCSDependency(
name=merged_base.name,
manager=merged_base.manager,
category=merged_base.category,
extras=merged_base.extras,
source=self.source,
vcs=self.vcs,
rev=self.rev or other.rev,
)


Dependency = Union[VersionedDependency, URLDependency, VCSDependency]

Expand Down
2 changes: 1 addition & 1 deletion conda_lock/src_parser/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def aggregate_lock_specs(
lock_spec.dependencies.get(platform, []) for lock_spec in lock_specs
):
key = (dep.manager, dep.name)
unique_deps[key] = dep
unique_deps[key] = dep.merge(unique_deps.get(key))

dependencies[platform] = list(unique_deps.values())

Expand Down

0 comments on commit 8783024

Please sign in to comment.