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

Recursively Parse Imported Modules #107

Merged
merged 19 commits into from
Sep 25, 2021
Merged
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
export NIX_PATH=nixpkgs=${pkgs.path}:nixos-config=${sample}/configuration.nix
cd nixui
'' + (if !enable-profiling then ''
python3 -m pytest
python3 -m pytest -vv
'' else ''
python3 -m cProfile -o profile -m pytest
python3 -c "import pstats; p = pstats.Stats('profile'); p.strip_dirs(); p.sort_stats('cumtime'); p.print_stats(50)"
Expand Down
38 changes: 19 additions & 19 deletions nixui/graphics/field_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@


def get_field_widget_classes_from_type(option_type):
if isinstance(option_type, types.ListOf):
if isinstance(option_type, types.ListOfType):
return [ListOfRedirect]
elif isinstance(option_type, types.AttrsOf):
elif isinstance(option_type, types.AttrsOfType):
return [AttrsOfRedirect]
elif isinstance(option_type, types.Attrs):
elif isinstance(option_type, types.AttrsType):
return [AttrsRedirect]
elif isinstance(option_type, types.Submodule):
elif isinstance(option_type, types.SubmoduleType):
return [SubmoduleRedirect]
elif isinstance(option_type, types.Either):
elif isinstance(option_type, types.EitherType):
widgets = set()
for subtype in option_type.subtypes:
widgets |= set(get_field_widget_classes_from_type(subtype))
return list(widgets)
elif isinstance(option_type, types.Unspecified):
elif isinstance(option_type, types.UnspecifiedType):
return [UndefinedField]
lapp0 marked this conversation as resolved.
Show resolved Hide resolved
elif isinstance(option_type, types.Null):
elif isinstance(option_type, types.NullType):
return [NullField]
elif isinstance(option_type, types.Bool):
elif isinstance(option_type, types.BoolType):
return [BooleanField]
elif isinstance(option_type, types.Str):
elif isinstance(option_type, types.StrType):
return [TextField]
elif isinstance(option_type, types.Int):
elif isinstance(option_type, types.IntType):
return [IntegerField]
elif isinstance(option_type, types.OneOf):
elif isinstance(option_type, types.OneOfType):
return [OneOfField]
elif isinstance(option_type, types.Path):
elif isinstance(option_type, types.PathType):
return [NotImplementedField]
elif isinstance(option_type, types.Package):
elif isinstance(option_type, types.PackageType):
return [NotImplementedField]
elif isinstance(option_type, types.Function):
elif isinstance(option_type, types.FunctionType):
return [NotImplementedField]
elif isinstance(option_type, types.Anything):
elif isinstance(option_type, types.AnythingType):
return [NotImplementedField]
else:
raise NotImplementedError(option_type)
Expand Down Expand Up @@ -210,22 +210,22 @@ def __init__(self, option, *args, **kwargs):


class SubmoduleRedirect(Redirect):
option_type = types.Submodule
option_type = types.SubmoduleType
name = "Submodule"


class ListOfRedirect(Redirect):
option_type = types.ListOf
option_type = types.ListOfType
name = "List of"


class AttrsRedirect(Redirect):
option_type = types.Attrs
option_type = types.AttrsType
name = "Attrs"


class AttrsOfRedirect(Redirect):
option_type = types.AttrsOf
option_type = types.AttrsOfType
name = "Attrs of"


Expand Down
2 changes: 1 addition & 1 deletion nixui/graphics/nav_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def set_option_path(self, option_path, option_type=None):
# if 10 or fewer options, navlist with lowest level attribute selected and list of editable fields to the right
# otherwise, show list of attributes within the clicked attribute and blank to the right
# TODO: option type checking should probably take place in the same place where all type -> field resolving occurs
if option_type in (types.Attrs, types.AttrsOf, types.ListOf) or num_children > 10:
if option_type in (types.AttrsType, types.AttrsOfType, types.ListOfType) or num_children > 10:
self.nav_list.replace_widget(
navlist.GenericNavListDisplay(
self.statemodel,
Expand Down
4 changes: 2 additions & 2 deletions nixui/graphics/navlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ def __new__(cls, statemodel, set_option_path_fn, option_path, option_type=None,
option_type = types.from_nix_type_str(
api.get_option_tree().get_type(option_path)
)
if option_type == types.AttrsOf:
if option_type == types.AttrsOfType:
return DynamicAttrsOf(statemodel, option_path, set_option_path_fn, selected)
elif option_type == types.ListOf:
elif option_type == types.ListOfType:
return DynamicListOf(statemodel, option_path, set_option_path_fn, selected)
else:
return StaticAttrsOf(option_path, set_option_path_fn, selected)
Expand Down
8 changes: 7 additions & 1 deletion nixui/nix/lib.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ in lib.makeExtensible (self: {

/* Extract the declarations of a module
*/
evalModuleStub = module_path: import module_path { inherit lib; name = ""; config = {}; pkgs = {}; };
evalModuleStub = module_path: import module_path {
inherit lib;
name = "";
config = {};
pkgs = {};
modulesPath = builtins.dirOf module_path;
};

/* Get all NixOS options as a list of options with the following schema:
{
Expand Down
10 changes: 8 additions & 2 deletions nixui/options/nix_eval.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
import json
import subprocess
import functools
Expand Down Expand Up @@ -58,11 +57,13 @@ def nix_instantiate_eval(expr, strict=False, show_trace=False, retry_show_trace_
err_str = err.decode('ISO-8859-1')
raise NixEvalError(err_str)


@contextmanager
def find_library(name):
with importlib.resources.path('nixui.nix', f'lib.nix') as f:
yield f'(import {f}).{name}'


@cache_by_unique_installed_nixos_nixpkgs_version
def get_all_nixos_options():
"""
Expand Down Expand Up @@ -100,6 +101,11 @@ def get_modules_import_position(module_path):
# TODO: should be part of lib.nix
expression = f"""
builtins.unsafeGetAttrPos "imports"
(import {module_path} {{config = {{}}; pkgs = import <nixpkgs> {{}}; lib = {{}};}})
(import {module_path} {{
config = {{}};
pkgs = import <nixpkgs> {{}};
lib = {{}};
modulesPath = builtins.dirOf {module_path};
}})
"""
return nix_instantiate_eval(expression, strict=True)