Unverified Commit 2d1799ff authored by h7x4's avatar h7x4 Committed by GitHub
Browse files

pkgs-lib/pythonVars: add support for imports and lib.mkRaw (#444053)

parents 364591a8 b7cdcad8
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -358,6 +358,37 @@ have a predefined type and string generator already declared under

    :   Outputs the xml with header.

`pkgs.formats.pythonVars` { }

:   A function taking an empty attribute set (for future extensibility)
    and returning a set with python variable specific attributes `type`, `lib`, and
    `generate` as specified [below](#pkgs-formats-result).

    The `lib` attribute contains functions to be used in settings, for
    generating special Python values:

    `mkRaw pythonCode`

    :   Outputs the given string as raw Python code

    `_imports`

    `_imports` is a special value you can set to specify additional modules to be
    imported on top of the file.

    `Example usage:`

    ```nix
      let
        format = pkgs.formats.pythonVars { };
      in {
        _imports = [ "re" ];

        conditional = format.lib.mkRaw "1 if True else 2";
        function_result = format.lib.mkRaw "re.findall(r'\\bf[a-z]*', 'which foot or hand fell fastest')";
      }
    ```

`pkgs.formats.cdn` { }

:   A function taking an empty attribute set (for future extensibility)
+37 −2
Original line number Diff line number Diff line
@@ -988,6 +988,14 @@ optionalAttrs allowAliases aliases
            };
        in
        attrsOf valueType;

      lib = {
        mkRaw = value: {
          inherit value;
          _type = "raw";
        };
      };

      generate =
        name: value:
        pkgs.callPackage (
@@ -1002,16 +1010,43 @@ optionalAttrs allowAliases aliases
                python3
                black
              ];
              value = builtins.toJSON value;
              imports = builtins.toJSON (value._imports or [ ]);
              value = builtins.toJSON (removeAttrs value [ "_imports" ]);
              pythonGen = ''
                import json
                import os

                def recursive_repr(value: any) -> str:
                    if type(value) is list:
                        return '\n'.join([
                            "[",
                            *[recursive_repr(x) + "," for x in value],
                            "]",
                        ])
                    elif type(value) is dict and value.get("_type") == "raw":
                        return value.get("value")
                    elif type(value) is dict:
                        return '\n'.join([
                            "{",
                            *[f"'{k.replace('\''', '\\\''')}': {recursive_repr(v)}," for k, v in value.items()],
                            "}",
                        ])
                    else:
                        return repr(value)

                with open(os.environ["importsPath"], "r") as f:
                    imports = json.load(f)
                    if imports is not None:
                        for i in imports:
                            print(f"import {i}")
                        print()

                with open(os.environ["valuePath"], "r") as f:
                    for key, value in json.load(f).items():
                        print(f"{key} = {repr(value)}")
                        print(f"{key} = {recursive_repr(value)}")
              '';
              passAsFile = [
                "imports"
                "value"
                "pythonGen"
              ];
+57 −0
Original line number Diff line number Diff line
@@ -904,6 +904,63 @@ runBuildTests {
    '';
  };

  pythonVars = shouldPass (
    let
      format = formats.pythonVars { };
    in
    {
      inherit format;
      input = {
        _imports = [
          "re"
          "a.b.c"
        ];

        int = 10;
        float = 3.141;
        bool = true;
        str = "foo";
        str_special = "foo\ntesthello'''";
        null = null;
        list = [
          null
          1
          "str"
          true
          (format.lib.mkRaw "1 if True else 2")
        ];
        attrs = {
          foo = null;
          conditional = format.lib.mkRaw "1 if True else 2";
        };
        func = format.lib.mkRaw "re.findall(r'\\bf[a-z]*', 'which foot or hand fell fastest')";
      };
      expected = ''
        import re
        import a.b.c

        attrs = {
            "conditional": 1 if True else 2,
            "foo": None,
        }
        bool = True
        float = 3.141
        func = re.findall(r"\bf[a-z]*", "which foot or hand fell fastest")
        int = 10
        list = [
            None,
            1,
            "str",
            True,
            1 if True else 2,
        ]
        null = None
        str = "foo"
        str_special = "foo\ntesthello''''"
      '';
    }
  );

  phpReturn = shouldPass {
    format = formats.php { };
    input = {