Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start work on type things #1218

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions conda_forge_tick/auto_tick.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,6 @@ def run(

branch_name = migrator.remote_branch(feedstock_ctx) + "_h" + uuid4().hex[0:6]

if hasattr(migrator, "name"):
assert isinstance(migrator.name, str)
migrator_name = migrator.name.lower().replace(" ", "")
else:
migrator_name = migrator.__class__.__name__.lower()

# TODO: run this in parallel
feedstock_dir, repo = get_repo(
ctx=migrator.ctx.session,
Expand All @@ -173,9 +167,7 @@ def run(

# migrate the feedstock
migrator.run_pre_piggyback_migrations(recipe_dir, feedstock_ctx.attrs, **kwargs)

# TODO - make a commit here if the repo changed

migrate_return = migrator.migrate(recipe_dir, feedstock_ctx.attrs, **kwargs)

if not migrate_return:
Expand Down Expand Up @@ -237,9 +229,11 @@ def run(
if (
migrator.check_solvable
# we always let stuff in cycles go
and feedstock_ctx.attrs["name"] not in getattr(migrator, "cycles", set())
and feedstock_ctx.attrs["feedstock_name"]
not in getattr(migrator, "cycles", set())
# we always let stuff at the top go
and feedstock_ctx.attrs["name"] not in getattr(migrator, "top_level", set())
and feedstock_ctx.attrs["feedstock_name"]
not in getattr(migrator, "top_level", set())
# for solveability always assume automerge is on.
and feedstock_ctx.attrs["conda-forge.yml"].get("bot", {}).get("automerge", True)
) or feedstock_ctx.attrs["conda-forge.yml"].get("bot", {}).get(
Expand All @@ -251,7 +245,9 @@ def run(
pre_key = "pre_pr_migrator_status"
if pre_key not in feedstock_ctx.attrs:
feedstock_ctx.attrs[pre_key] = {}
feedstock_ctx.attrs[pre_key][migrator_name] = "not solvable: %s" % sorted(
feedstock_ctx.attrs[pre_key][
migrator.sanitized_name
] = "not solvable: %s" % sorted(
set(errors),
)
eval_cmd(f"rm -rf {feedstock_dir}")
Expand All @@ -262,7 +258,7 @@ def run(
if (
isinstance(migrator, MigrationYaml)
and not diffed_files
and feedstock_ctx.attrs["name"] != "conda-forge-pinning"
and feedstock_ctx.attrs["feedstock_name"] != "conda-forge-pinning"
):
# spoof this so it looks like the package is done
pr_json = {
Expand All @@ -274,7 +270,7 @@ def run(
# push up
try:
# TODO: remove this hack, but for now this is the only way to get
# the feedstock dir into pr_body
# the feedstock dir into pr_body
feedstock_ctx.feedstock_dir = feedstock_dir
pr_json = push_repo(
session_ctx=migrator.ctx.session,
Expand Down Expand Up @@ -305,8 +301,6 @@ def run(
# from .dynamo_models import PRJson

# PRJson.dump(pr_json)
# If we've gotten this far then the node is good
feedstock_ctx.attrs["bad"] = False
logger.info("Removing feedstock dir")
eval_cmd(f"rm -rf {feedstock_dir}")
return migrate_return, ljpr
Expand All @@ -331,7 +325,7 @@ def add_replacement_migrator(
old_pkg: "PackageName",
new_pkg: "PackageName",
rationale: str,
alt_migrator: Union[Migrator, None] = None,
alt_migrator: Optional[Migrator] = None,
) -> None:
"""Adds a migrator to replace one package with another.

Expand Down Expand Up @@ -584,7 +578,7 @@ def migration_factory(
logger.warning("skipping migration %s because it is paused", __mname)


def _outside_pin_range(pin_spec, current_pin, new_version):
def _outside_pin_range(pin_spec: str, current_pin: str, new_version: str) -> bool:
pin_level = len(pin_spec.split("."))
current_split = current_pin.split(".")
new_split = new_version.split(".")
Expand All @@ -597,7 +591,10 @@ def _outside_pin_range(pin_spec, current_pin, new_version):
return False


def create_migration_yaml_creator(migrators: MutableSequence[Migrator], gx: nx.DiGraph):
def create_migration_yaml_creator(
migrators: MutableSequence[Migrator],
gx: nx.DiGraph,
) -> None:
with indir(os.environ["CONDA_PREFIX"]):
pinnings = parse_config_file(
"conda_build_config.yaml",
Expand Down Expand Up @@ -710,7 +707,7 @@ def initialize_migrators(
gx,
"matplotlib",
"matplotlib-base",
("Unless you need `pyqt`, recipes should depend only on " "`matplotlib-base`."),
"Unless you need `pyqt`, recipes should depend only on " "`matplotlib-base`.",
alt_migrator=MatplotlibBase,
)
create_migration_yaml_creator(migrators=MIGRATORS, gx=gx)
Expand Down
42 changes: 26 additions & 16 deletions conda_forge_tick/migrators/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
AttrsTypedDict,
MigrationUidTypedDict,
PackageName,
FeedstockName,
PRedElementTypedDict,
OutputsLUT,
)
from conda_forge_tick.utils import JsonFriendly

Expand Down Expand Up @@ -113,13 +116,15 @@ def __init__(
# TODO: Validate this?
obj_version: Optional[int] = None,
piggy_back_migrations: Optional[Sequence[MiniMigrator]] = None,
check_solvable=True,
check_solvable: bool = True,
):
self.piggy_back_migrations = piggy_back_migrations or []
self.pr_limit = pr_limit
self.obj_version = obj_version
self.ctx: MigratorContext = None
self.check_solvable = check_solvable
self.name = self.__class__.__name__.lower()
self.sanitized_name = self.name.lower().replace(" ", "")

def bind_to_ctx(self, migrator_ctx: MigratorContext) -> None:
self.ctx = migrator_ctx
Expand Down Expand Up @@ -405,17 +410,19 @@ def migrator_label(cls) -> dict:


class GraphMigrator(Migrator):
outputs_lut: OutputsLUT

def __init__(
self,
*,
name: Optional[str] = None,
graph: nx.DiGraph = None,
pr_limit: int = 0,
top_level: Set["PackageName"] = None,
cycles: Optional[Sequence["packageName"]] = None,
top_level: Set[FeedstockName] = None,
cycles: Optional[Sequence[FeedstockName]] = None,
obj_version: Optional[int] = None,
piggy_back_migrations: Optional[Sequence[MiniMigrator]] = None,
check_solvable=True,
check_solvable: bool = True,
):
super().__init__(
pr_limit,
Expand All @@ -439,7 +446,9 @@ def __init__(
for k in node.get("payload", {}).get("outputs_names", [])
}

self.name = name
if name:
self.name = name
self.sanitized_name = self.name.lower().replace(" ", "")
self.top_level = top_level or set()
self.cycles = set(chain.from_iterable(cycles or []))

Expand All @@ -451,27 +460,28 @@ def predecessors_not_yet_built(self, attrs: "AttrsTypedDict") -> bool:
except KeyError as e:
print(node)
raise e

# Any archived nodes don't count so we skip them
if payload.get("archived", False):
continue

muid = frozen_to_json_friendly(self.migrator_uid(payload))
if (
muid
not in _sanitized_muids(
payload.get("PRed", []),
)
and not payload.get("archived", False)
if muid not in _sanitized_muids(
payload.get("PRed", []),
):
return True

# This is due to some PRed_json loss due to bad graph deploy outage
m_pred_json: PRedElementTypedDict
for m_pred_json in payload.get("PRed", []):
if m_pred_json["data"] == muid["data"]:
break
# If we can't find the uid data in the pred json then we haven't made the pr
else:
m_pred_json = None
return False
# note that if the bot is missing the PR we assume it is open
# so that errors halt the migration and can be fixed
if (
m_pred_json
and m_pred_json.get("PR", {"state": "open"}).get("state", "") == "open"
):
if m_pred_json.get("PR", {"state": "open"}).get("state", "") == "open":
return True
return False

Expand Down
16 changes: 8 additions & 8 deletions conda_forge_tick/migrators/migration_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@

from conda_forge_tick.contexts import FeedstockContext
from conda_forge_tick.migrators.core import GraphMigrator, MiniMigrator, Migrator
from conda_forge_tick.utils import eval_cmd, pluck, pin_sep_pat
from conda_forge_tick.xonsh_utils import indir
from conda_forge_tick.utils import eval_cmd
from ..utils import pluck, pin_sep_pat

if typing.TYPE_CHECKING:
from ..migrators_types import (
MigrationUidTypedDict,
AttrsTypedDict,
PackageName,
RequirementsTypedDict,
)

logger = logging.getLogger("conda_forge_tick.migrators.migration_yaml")


def _patch_dict(cfg, patches):
def _patch_dict(cfg: dict, patches: dict) -> None:
"""Patch a dictionary using a set of patches.

Given a dict like
Expand Down Expand Up @@ -77,7 +77,7 @@ def _patch_dict(cfg, patches):
logger.warning("conda-forge.yml patch %s: %s did not work!", k, v)


def merge_migrator_cbc(migrator_yaml: str, conda_build_config_yaml: str):
def merge_migrator_cbc(migrator_yaml: str, conda_build_config_yaml: str) -> str:
"""Merge a migrator_yaml with the conda_build_config_yaml"""
migrator_keys = defaultdict(list)
current_key = None
Expand Down Expand Up @@ -129,8 +129,8 @@ def __init__(
bump_number: int = 1,
piggy_back_migrations: Optional[Sequence[MiniMigrator]] = None,
automerge: bool = False,
check_solvable=True,
conda_forge_yml_patches=None,
check_solvable: bool = True,
conda_forge_yml_patches: dict = None,
**kwargs: Any,
):
super().__init__(
Expand Down Expand Up @@ -421,11 +421,11 @@ def order(
)


def _req_is_python(req):
def _req_is_python(req: str) -> bool:
return pin_sep_pat.split(req)[0].strip().lower() == "python"


def _all_noarch(attrs, only_python=False):
def _all_noarch(attrs: AttrsTypedDict, only_python: bool = False) -> bool:
meta_yaml = attrs.get("meta_yaml", {}) or {}

if not only_python:
Expand Down
17 changes: 13 additions & 4 deletions conda_forge_tick/migrators_types.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from typing import Any, Dict, List, Set, Tuple, Union, Optional
from mypy_extensions import TypedDict

PackageName = typing.NewType("PackageName", str)
FeedstockName = typing.NewType("FeedstockName", str)

class AboutTypedDict(TypedDict, total=False):
description: str
Expand Down Expand Up @@ -80,15 +81,18 @@ class MigrationUidTypedDict(TypedDict, total=False):
migrator_object_version: int
# Used by version migrators
version: str
# Used by MigrationYamlCreator
pin_version: str

class PackageTypedDict(TypedDict):
name: str
version: str

class RequirementsTypedDict(TypedDict, total=False):
build: List[str]
host: List[str]
run: List[str]
build: Set[PackageName]
host: Set[PackageName]
run: Set[PackageName]
test: Set[PackageName]

class SourceTypedDict(TypedDict, total=False):
fn: str
Expand All @@ -106,7 +110,7 @@ class AttrsTypedDict_(TypedDict, total=False):
about: AboutTypedDict
build: BuildTypedDict
extra: ExtraTypedDict
feedstock_name: str
feedstock_name: FeedstockName
meta_yaml: MetaYamlTypedDict
package: PackageTypedDict
raw_meta_yaml: str
Expand All @@ -122,13 +126,18 @@ class AttrsTypedDict_(TypedDict, total=False):
bad: Union[bool, str]
# TODO: ADD in
# "conda-forge.yml":
pre_pr_migrator_status: Dict[str, str]

class CondaForgeYamlContents(TypedDict, total=False):
provider: Dict[str, str]
bot: Dict[str, str]

CondaForgeYaml = TypedDict(
"CondaForgeYaml", {"conda-forge.yml": CondaForgeYamlContents}
)

class AttrsTypedDict(AttrsTypedDict_, CondaForgeYaml):
pass


OutputsLUT = Dict[PackageName, FeedstockName]
8 changes: 4 additions & 4 deletions conda_forge_tick/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

if typing.TYPE_CHECKING:
from mypy_extensions import TypedDict, TestTypedDict
from .migrators_types import PackageName, RequirementsTypedDict
from .migrators_types import PackageName, RequirementsTypedDict, AttrsTypedDict_
from conda_forge_tick.migrators_types import MetaYamlTypedDict


Expand Down Expand Up @@ -78,7 +78,7 @@
)


def eval_cmd(cmd, **kwargs):
def eval_cmd(cmd: str, **kwargs: Any) -> str:
"""run a command capturing stdout

stderr is printed for debugging
Expand Down Expand Up @@ -679,12 +679,12 @@ def _fetch_static_repo(name, dest):

def populate_feedstock_attributes(
name: str,
sub_graph: typing.MutableMapping,
sub_graph: "AttrsTypedDict_",
meta_yaml: typing.Union[str, Response] = "",
conda_forge_yaml: typing.Union[str, Response] = "",
mark_not_archived=False,
feedstock_dir=None,
) -> typing.MutableMapping:
) -> AttrsTypedDict_:
"""Parse the various configuration information into something usable

Notes
Expand Down