Skip to content

Commit

Permalink
Revert "Fixes several issues found by the new Grapher module work (#105
Browse files Browse the repository at this point in the history
…)"

This reverts commit 26eab68.
  • Loading branch information
schuylermartin45 authored Sep 3, 2024
1 parent 26eab68 commit 68b405d
Show file tree
Hide file tree
Showing 8 changed files with 15 additions and 554 deletions.
4 changes: 2 additions & 2 deletions conda_recipe_manager/grapher/recipe_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ def __init__(
match dep.type:
# Build graph
case DependencySection.BUILD | DependencySection.HOST:
self._build_graph.add_edge(package_name, dep.data.name) # type: ignore[misc]
self._build_graph.add_edge(package_name, dep.match_spec.name) # type: ignore[misc]

# Test graph
# TODO does this include run constraints?
case DependencySection.RUN | DependencySection.TESTS:
self._test_graph.add_edge(package_name, dep.data.name) # type: ignore[misc]
self._test_graph.add_edge(package_name, dep.match_spec.name) # type: ignore[misc]

def __bool__(self) -> bool:
"""
Expand Down
48 changes: 2 additions & 46 deletions conda_recipe_manager/parser/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from conda.models.match_spec import MatchSpec

from conda_recipe_manager.parser._types import Regex
from conda_recipe_manager.parser.selector_parser import SelectorParser
from conda_recipe_manager.parser.types import SchemaVersion

Expand Down Expand Up @@ -98,49 +97,6 @@ def str_to_dependency_section(s: str) -> Optional[DependencySection]:
return None


class DependencyVariable:
"""
Represents a dependency that contains a JINJA variable that is unable to be resolved by the recipe's variable table.
"""

def __init__(self, s: str):
"""
Constructs a DependencyVariable instance.
:param s: String to initialize the instance with.
"""
# Using `name` allows this class to be used trivially with MatchSpec without type guards.
# TODO normalize common JINJA functions for quote usage
self.name = s

def __eq__(self, o: object) -> bool:
"""
Checks to see if two objects are equivalent.
:param o: Other instance to check.
:returns: True if two DependencyVariable instances are equivalent. False otherwise.
"""
if not isinstance(o, DependencyVariable):
return False
return self.name == o.name


# Type alias for types allowed in a Dependency's `data` field.
DependencyData = MatchSpec | DependencyVariable


def dependency_data_from_string(s: str) -> DependencyData:
"""
Constructs a DataDependency object from a dependency string in a recipe file.
:param s: String to process.
:returns: A DataDependency instance.
"""
if Regex.JINJA_V1_SUB.search(s):
return DependencyVariable(s)
return MatchSpec(s)


class Dependency(NamedTuple):
"""
Structure that contains metadata about a dependency found in the recipe. This is immutable by design.
Expand All @@ -152,8 +108,8 @@ class Dependency(NamedTuple):
path: str
# Identifies what kind of dependency this is
type: DependencySection
# Parsed dependency. Identifies a name and version constraints
data: DependencyData
# Parses the dependency's name and version constraints
match_spec: MatchSpec
# The selector applied to this dependency, if applicable
selector: Optional[SelectorParser] = None

Expand Down
25 changes: 7 additions & 18 deletions conda_recipe_manager/parser/recipe_parser_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@

from typing import Final, Optional, cast

from conda.models.match_spec import MatchSpec

from conda_recipe_manager.parser._types import ROOT_NODE_VALUE
from conda_recipe_manager.parser.dependency import (
Dependency,
DependencyMap,
dependency_data_from_string,
str_to_dependency_section,
)
from conda_recipe_manager.parser.dependency import Dependency, DependencyMap, str_to_dependency_section
from conda_recipe_manager.parser.recipe_reader import RecipeReader
from conda_recipe_manager.parser.selector_parser import SelectorParser
from conda_recipe_manager.parser.types import SchemaVersion
Expand All @@ -37,7 +34,7 @@ def _add_top_level_dependencies(root_package: str, dep_map: DependencyMap) -> No
continue
# Change the "required_by" package name to the current package, not the root package name.
dep_map[package].extend(
[Dependency(package, d.path, d.type, d.data, d.selector) for d in root_dependencies]
[Dependency(package, d.path, d.type, d.match_spec, d.selector) for d in root_dependencies]
)

def _fetch_optional_selector(self, path: str) -> Optional[SelectorParser]:
Expand Down Expand Up @@ -101,8 +98,8 @@ def get_all_dependencies(self) -> DependencyMap:
root_package = package

requirements = cast(
dict[str, list[str | None]],
self.get_value(RecipeReader.append_to_path(path, "/requirements"), default={}, sub_vars=True),
dict[str, list[str]],
self.get_value(RecipeReader.append_to_path(path, "/requirements"), default=[], sub_vars=True),
)
dep_map[package] = []
for section_str, deps in requirements.items():
Expand All @@ -112,22 +109,14 @@ def get_all_dependencies(self) -> DependencyMap:
continue

for i, dep in enumerate(deps):
# Sanitize and ignore empty data. In theory, recipes shouldn't contain `Null`s or empty strings in
# their dependency lists, but we will guard against it out of an abundance of caution.
if dep is None:
continue
dep = dep.strip()
if not dep:
continue

# NOTE: `get_dependency_paths()` uses the same approach for calculating dependency paths.
dep_path = RecipeReader.append_to_path(path, f"/requirements/{section_str}/{i}")
dep_map[package].append(
Dependency(
required_by=package,
path=dep_path,
type=section,
data=dependency_data_from_string(dep),
match_spec=MatchSpec(dep),
selector=self._fetch_optional_selector(dep_path),
)
)
Expand Down
8 changes: 1 addition & 7 deletions conda_recipe_manager/parser/recipe_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,6 @@ def _set_on_schema_version() -> tuple[int, re.Pattern[str]]:
if lower_match:
value = value.lower()
s = s.replace(match, value)
# $-Escaping the unresolved variable does a few things:
# - Clearly identifies the value as an unresolved variable
# - Normalizes the substitution syntax with V1
# - Ensures the returned value is YAML-parsable
elif self._schema_version == SchemaVersion.V0:
s = f"${s}"
return cast(JsonType, yaml.safe_load(s))

def _init_vars_tbl(self) -> None:
Expand Down Expand Up @@ -743,7 +737,7 @@ def get_value(self, path: str, default: JsonType | SentinelType = _sentinel, sub
:param path: JSON patch (RFC 6902)-style path to a value.
:param default: (Optional) If the value is not found, return this value instead.
:param sub_vars: (Optional) If set to True and the value contains a Jinja template variable, the Jinja value
will be "rendered". Any variables that can't be resolved will be escaped with `${{ }}`.
will be "rendered".
:raises KeyError: If the value is not found AND no default is specified
:returns: If found, the value in the recipe at that path. Otherwise, the caller-specified default value.
"""
Expand Down
24 changes: 2 additions & 22 deletions conda_recipe_manager/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,10 @@
# Generic, hashable type
H = TypeVar("H", bound=Hashable)

# Bootstraps global singleton used by `SentinelType`
_schema_type_singleton: SentinelType


# All sentinel values used in this module should be constructed with this class, for typing purposes.
class SentinelType:
"""
A single sentinel class to be used in this project, as an alternative to `None` when `None` cannot be used.
It is defined in a way such that SentinelType instances survive pickling and allocations in different memory
spaces.
"""

def __new__(cls) -> SentinelType:
"""
Constructs a global singleton SentinelType instance, once.
:returns: The SentinelType instance
"""
# Credit to @dholth for suggesting this approach in PR #105.
global _schema_type_singleton
try:
return _schema_type_singleton
except NameError:
_schema_type_singleton = super().__new__(cls)
return _schema_type_singleton
pass


class MessageCategory(StrEnum):
Expand Down
75 changes: 0 additions & 75 deletions tests/parser/test_pickle_integration.py

This file was deleted.

Loading

0 comments on commit 68b405d

Please sign in to comment.