]> git.scottworley.com Git - pinch/blobdiff - pinch.py
Verify unknown config fields raise errors
[pinch] / pinch.py
index 266daffb35045fffd8b490a6e17f24b97169b42c..9b845e3414df7a5c66a0cd940890a8562ebf7da8 100644 (file)
--- a/pinch.py
+++ b/pinch.py
@@ -18,6 +18,7 @@ import urllib.request
 import xml.dom.minidom
 
 from typing import (
 import xml.dom.minidom
 
 from typing import (
+    Callable,
     Dict,
     Iterable,
     List,
     Dict,
     Iterable,
     List,
@@ -590,19 +591,24 @@ K = TypeVar('K')
 V = TypeVar('V')
 
 
 V = TypeVar('V')
 
 
-def filter_dict(d: Dict[K, V], fields: Set[K]
-                ) -> Tuple[Dict[K, V], Dict[K, V]]:
+def partition_dict(pred: Callable[[K, V], bool],
+                   d: Dict[K, V]) -> Tuple[Dict[K, V], Dict[K, V]]:
     selected: Dict[K, V] = {}
     remaining: Dict[K, V] = {}
     for k, v in d.items():
     selected: Dict[K, V] = {}
     remaining: Dict[K, V] = {}
     for k, v in d.items():
-        if k in fields:
+        if pred(k, v):
             selected[k] = v
         else:
             remaining[k] = v
     return selected, remaining
 
 
             selected[k] = v
         else:
             remaining[k] = v
     return selected, remaining
 
 
-def read_search_path(
+def filter_dict(d: Dict[K, V], fields: Set[K]
+                ) -> Tuple[Dict[K, V], Dict[K, V]]:
+    return partition_dict(lambda k, v: k in fields, d)
+
+
+def read_config_section(
         conf: configparser.SectionProxy) -> Tuple[SearchPath, Optional[Pin]]:
     mapping: Mapping[str, Tuple[Type[SearchPath], Type[Pin]]] = {
         'alias': (AliasSearchPath, AliasPin),
         conf: configparser.SectionProxy) -> Tuple[SearchPath, Optional[Pin]]:
     mapping: Mapping[str, Tuple[Type[SearchPath], Type[Pin]]] = {
         'alias': (AliasSearchPath, AliasPin),
@@ -618,6 +624,16 @@ def read_search_path(
     return SP(**remaining_fields), pin
 
 
     return SP(**remaining_fields), pin
 
 
+def read_pinned_config_section(
+        section: str, conf: configparser.SectionProxy) -> Tuple[SearchPath, Pin]:
+    sp, pin = read_config_section(conf)
+    if pin is None:
+        raise Exception(
+            'Cannot update unpinned channel "%s" (Run "pin" before "update")' %
+            section)
+    return sp, pin
+
+
 def read_config(filename: str) -> configparser.ConfigParser:
     config = configparser.ConfigParser()
     config.read_file(open(filename), filename)
 def read_config(filename: str) -> configparser.ConfigParser:
     config = configparser.ConfigParser()
     config.read_file(open(filename), filename)
@@ -643,7 +659,7 @@ def pinCommand(args: argparse.Namespace) -> None:
         if args.channels and section not in args.channels:
             continue
 
         if args.channels and section not in args.channels:
             continue
 
-        sp, old_pin = read_search_path(config[section])
+        sp, old_pin = read_config_section(config[section])
 
         config[section].update(sp.pin(v, old_pin)._asdict())
 
 
         config[section].update(sp.pin(v, old_pin)._asdict())
 
@@ -654,23 +670,24 @@ def pinCommand(args: argparse.Namespace) -> None:
 def updateCommand(args: argparse.Namespace) -> None:
     v = Verification()
     exprs: Dict[str, str] = {}
 def updateCommand(args: argparse.Namespace) -> None:
     v = Verification()
     exprs: Dict[str, str] = {}
-    config = read_config_files(args.channels_file)
-    for section in config:
-        sp, pin = read_search_path(config[section])
-        if pin is None:
-            raise Exception(
-                'Cannot update unpinned channel "%s" (Run "pin" before "update")' %
-                section)
-        if isinstance(sp, AliasSearchPath):
-            continue
+    config = {
+        section: read_pinned_config_section(section, conf) for section,
+        conf in read_config_files(
+            args.channels_file).items()}
+    alias, nonalias = partition_dict(
+        lambda k, v: isinstance(v[0], AliasSearchPath), config)
+
+    for section, (sp, pin) in nonalias.items():
+        assert not isinstance(sp, AliasSearchPath)  # mypy can't see through
+        assert not isinstance(pin, AliasPin)        # partition_dict()
         tarball = sp.fetch(v, pin)
         exprs[section] = (
             'f: f { name = "%s"; channelName = "%%s"; src = builtins.storePath "%s"; }' %
         tarball = sp.fetch(v, pin)
         exprs[section] = (
             'f: f { name = "%s"; channelName = "%%s"; src = builtins.storePath "%s"; }' %
-            (config[section]['release_name'], tarball))
+            (pin.release_name, tarball))
 
 
-    for section in config:
-        if 'alias_of' in config[section]:
-            exprs[section] = exprs[str(config[section]['alias_of'])]
+    for section, (sp, pin) in alias.items():
+        assert isinstance(sp, AliasSearchPath)  # For mypy
+        exprs[section] = exprs[sp.alias_of]
 
     command = [
         'nix-env',
 
     command = [
         'nix-env',