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

Print top-level errors normally in nix repl #10209

Merged
Merged
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
3 changes: 2 additions & 1 deletion src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ struct NixRepl
.force = true,
.derivationPaths = true,
.maxDepth = maxDepth,
.prettyIndent = 2
.prettyIndent = 2,
.errors = ErrorPrintBehavior::ThrowTopLevel,
});
}
};
Expand Down
30 changes: 29 additions & 1 deletion src/libexpr/print-options.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@

namespace nix {

/**
* How errors should be handled when printing values.
*/
enum class ErrorPrintBehavior {
/**
* Print the first line of the error in brackets: `«error: oh no!»`
*/
Print,
/**
* Throw the error to the code that attempted to print the value, instead
* of suppressing it it.
*/
Throw,
/**
* Only throw the error if encountered at the top level of the expression.
*
* This will cause expressions like `builtins.throw "uh oh!"` to throw
* errors, but will print attribute sets and other nested structures
* containing values that error (like `nixpkgs`) normally.
*/
ThrowTopLevel,
};
Comment on lines +14 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this (hidden) configurability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the comments not make it clear enough? Let me know how I can improve it. Output snipped for brevity, but basically if the whole expression errors we want to print the error message normally, but in nested structures like attribute sets or lists we want to show error messages for specific attributes (to get a good overview for structures like nixpkgs):

nix-repl> pkgs.pythonPackages.APScheduler
error:
       … in the condition of the assert statement
         at /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/lib/customisation.nix:268:17
       … in the left operand of the OR (||) operator
         at /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/pkgs/development/interpreters/python/passthrufun.nix:28:45

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: Package ‘python-2.7.18.7’ in /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/pkgs/development/interpreters/python/cpython/2.7/default.nix:335 is marked as insecure, refusing to evaluate.


       Known issues:
        - Python 2.7 has reached its end of life after 2020-01-01. See https://www.python.org/doc/sunset-python-2/.

       You can install it anyway by allowing this package, using the
       following methods:

       a) To temporarily allow all insecure packages, you can use an environment
          variable for a single invocation of the nix tools:

            $ export NIXPKGS_ALLOW_INSECURE=1

          Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake,
                then pass `--impure` in order to allow use of environment variables.
...
nix-repl> pkgs.pythonPackages
{
  APScheduler = «error: Package ‘python-2.7.18.7’ in /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/pkgs/development/interpreters/python/cpython/2.7/default.nix:335 is marked as insecure, refusing to evaluate.»;
  BTrees = «error: Package ‘python-2.7.18.7’ in /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/pkgs/development/interpreters/python/cpython/2.7/default.nix:335 is marked as insecure, refusing to evaluate.»;
  Babel = «error: Package ‘python-2.7.18.7’ in /nix/store/wmj6j3afrvqxsjpad47nrad1vrwmykrg-source/pkgs/development/interpreters/python/cpython/2.7/default.nix:335 is marked as insecure, refusing to evaluate.»;
error: interrupted by the user

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry, I missed the bit about this not being repl-specific. Forget about my comment.

(I guess we're never using the Throw variant, but it doesn't harm to have it either)


/**
* Options for printing Nix values.
*/
Expand Down Expand Up @@ -68,6 +91,11 @@ struct PrintOptions
*/
size_t prettyIndent = 0;

/**
* How to handle errors encountered while printing values.
*/
ErrorPrintBehavior errors = ErrorPrintBehavior::Print;

/**
* True if pretty-printing is enabled.
*/
Expand All @@ -86,7 +114,7 @@ static PrintOptions errorPrintOptions = PrintOptions {
.maxDepth = 10,
.maxAttrs = 10,
.maxListItems = 10,
.maxStringLength = 1024
.maxStringLength = 1024,
};

}
120 changes: 60 additions & 60 deletions src/libexpr/print.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,25 +271,21 @@ class Printer

void printDerivation(Value & v)
{
try {
Bindings::iterator i = v.attrs->find(state.sDrvPath);
NixStringContext context;
std::string storePath;
if (i != v.attrs->end())
storePath = state.store->printStorePath(state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"));
Bindings::iterator i = v.attrs->find(state.sDrvPath);
NixStringContext context;
std::string storePath;
if (i != v.attrs->end())
storePath = state.store->printStorePath(state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"));

if (options.ansiColors)
output << ANSI_GREEN;
output << "«derivation";
if (!storePath.empty()) {
output << " " << storePath;
}
output << "»";
if (options.ansiColors)
output << ANSI_NORMAL;
} catch (Error & e) {
printError_(e);
if (options.ansiColors)
output << ANSI_GREEN;
output << "«derivation";
if (!storePath.empty()) {
output << " " << storePath;
}
output << "»";
if (options.ansiColors)
output << ANSI_NORMAL;
}

bool shouldPrettyPrintAttrs(AttrVec & v)
Expand Down Expand Up @@ -510,64 +506,68 @@ class Printer
output.flush();
checkInterrupt();

if (options.force) {
try {
try {
if (options.force) {
state.forceValue(v, v.determinePos(noPos));
} catch (Error & e) {
printError_(e);
return;
}
}

switch (v.type()) {
switch (v.type()) {

case nInt:
printInt(v);
break;
case nInt:
printInt(v);
break;

case nFloat:
printFloat(v);
break;
case nFloat:
printFloat(v);
break;

case nBool:
printBool(v);
break;
case nBool:
printBool(v);
break;

case nString:
printString(v);
break;
case nString:
printString(v);
break;

case nPath:
printPath(v);
break;
case nPath:
printPath(v);
break;

case nNull:
printNull();
break;
case nNull:
printNull();
break;

case nAttrs:
printAttrs(v, depth);
break;
case nAttrs:
printAttrs(v, depth);
break;

case nList:
printList(v, depth);
break;
case nList:
printList(v, depth);
break;

case nFunction:
printFunction(v);
break;
case nFunction:
printFunction(v);
break;

case nThunk:
printThunk(v);
break;
case nThunk:
printThunk(v);
break;

case nExternal:
printExternal(v);
break;
case nExternal:
printExternal(v);
break;

default:
printUnknown();
break;
default:
printUnknown();
break;
}
} catch (Error & e) {
if (options.errors == ErrorPrintBehavior::Throw
|| (options.errors == ErrorPrintBehavior::ThrowTopLevel
&& depth == 0)) {
throw;
}
printError_(e);
}
}

Expand Down
Loading