Repository: conda-forge/conda-smithy

Issue:
ENH: Define package hints in a place that doesn't need a new linter version for updates
In #1734, I added a dictionary `specific_hints`, which built upon existing nudges (e.g. about matplotlib-base), and is meant to be both performant and extensible:

> As a [side note](https://github.com/conda-forge/conda-smithy/pull/1734#discussion_r1186575235), I made this a dictionary (rather than a chain of cases) because I expect this list to grow substantially and wanted to keep performance snappy (checking dict membership is fast in python).
> 
> The anticipated growth is not mainly due to renamings, but because I think it would be useful for all kinds of output-hygiene (e.g. packages from archived/abandoned/superseded feedstocks, like all the ancient "homegrown" cuda feedstocks).

 @beckermr noted:

> It'd be nice to store this metadata somewhere else so that we can add to it without making a smithy release. This can happen in another PR though.

I agree that this would be good. Opening this issue to discuss where we should keep that information, and how the linter would interface with it.


Discussion:
I think we could simply serve it out of the docs repo and point back to a GitHub raw url. 
I was looking at this again. Do you have a preferred path in mind in the docs repo? Something like [`misc/`](https://github.com/conda-forge/conda-forge.github.io/blob/main/misc)?

I'm thinking it would be nice to make it a TOML file (instead of say, a json, like already present in `misc/`), so we can keep comments. Though YAML would also work of course, and is more wide-spread in our infra...
Another option is to ship it as part of the conda-forge-metadata package, though this may have other implications. We could make the dependence optional. We could also put it in the pinnings repo. This last idea actually sounds better to me since the migrators for renames go there as well. We can add the hint when we write the migrator. 
Fine by me to do it in pinnings repo. Where would you like to put it? Under `recipe/linter`?
Definitely inside the recipe dir. I don't care otherwise. 
First PR: https://github.com/conda-forge/conda-forge-pinning-feedstock/pull/4926
(second PR to smithy to come once we merge the first)
Let's close this when we're actually using it.

Resolving patch:
diff --git a/conda_smithy/lint_recipe.py b/conda_smithy/lint_recipe.py
--- a/conda_smithy/lint_recipe.py
+++ b/conda_smithy/lint_recipe.py
@@ -18,6 +18,11 @@
 
 import github
 
+if sys.version_info[:2] < (3, 11):
+    import tomli as tomllib
+else:
+    import tomllib
+
 from conda_build.metadata import (
     ensure_valid_license_family,
     FIELDS as cbfields,
@@ -926,29 +931,14 @@ def run_conda_forge_specific(meta, recipe_dir, lints, hints):
         else:
             run_reqs += _req
 
-    specific_hints = {
-        "matplotlib": (
-            "Recipes should usually depend on `matplotlib-base` as opposed to "
-            "`matplotlib` so that runtime environments do not require large "
-            "packages like `qt`."
-        ),
-        "jpeg": (
-            "Recipes should usually depend on `libjpeg-turbo` as opposed to "
-            "`jpeg` for improved performance. For more information please see"
-            "https://github.com/conda-forge/conda-forge.github.io/issues/673"
-        ),
-        "pytorch-cpu": (
-            "Please depend on `pytorch` directly, in order to avoid forcing "
-            "CUDA users to downgrade to the CPU version for no reason."
-        ),
-        "pytorch-gpu": (
-            "Please depend on `pytorch` directly. If your package definitely "
-            "requires the CUDA version, please depend on `pytorch =*=cuda*`."
-        ),
-        "abseil-cpp": "The `abseil-cpp` output has been superseded by `libabseil`",
-        "grpc-cpp": "The `grpc-cpp` output has been superseded by `libgrpc`",
-        "build": "The pypa `build` package has been renamed to `python-build`",
-    }
+    hints_toml_url = "https://raw.githubusercontent.com/conda-forge/conda-forge-pinning-feedstock/main/recipe/linter_hints/hints.toml"
+    hints_toml_req = requests.get(hints_toml_url)
+    if hints_toml_req.status_code != 200:
+        # too bad, but not important enough to throw an error;
+        # linter will rerun on the next commit anyway
+        return
+    hints_toml_str = hints_toml_req.content.decode("utf-8")
+    specific_hints = tomllib.loads(hints_toml_str)["hints"]
 
     for rq in build_reqs + host_reqs + run_reqs:
         dep = rq.split(" ")[0].strip()


Test patch: