-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Experimental python bindings #7735
base: master
Are you sure you want to change the base?
Changes from 1 commit
2e37594
ed8c80b
5dc8bcb
de148e4
827f634
410393f
8837e42
4599be3
be36946
e3f56e9
2c3e1c8
9b27833
d272171
b8003d6
a1669ed
33ca7e3
7dee1c5
5bc4948
6f8108c
446db64
481f28c
668313f
96621a0
0503a73
1b0960f
d8ce01b
9627862
a91f312
06d7135
34c8519
91b0740
56ef3e3
8d734cd
f5fd435
68996d8
22c9e48
fb5884e
f1442f8
0d52ddc
51440a3
2cb9dd0
57e71a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import nix | ||
|
||
def greet(): | ||
print("Evaluating 1 + 1 in Nix gives: " + str(nix.eval("1 + 1"))) | ||
print("Evaluating 1 + 1 in Nix gives: " + str(nix.callExprString("_: 1 + 1", None))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,64 +5,65 @@ | |
class TestPythonNix(unittest.TestCase): | ||
def test_dict(self): | ||
val = dict(a=1) | ||
self.assertEqual(nix.eval("a", vars=dict(a=val)), val) | ||
self.assertEqual(nix.callExprString("{ a }: a", arg=dict(a=val)), val) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As previously hinted, in the latest commit I now changed the API to a more explicit function call like nix.eval("{ a }: a", arg=dict(a=1)) from the original nix.eval("a", vars=dict(a=1)) because that worked the same as However, after noticing that it's now very odd when you don't need to take any arguments, like this: nix.callExprString("{}: null", arg={}) I decided to reinvestigate the original idea, and whether Looking into this I'm concluding that the three issues listed there shouldn't be a problem for the Python bindings, see the above issue for more context:
Because of that I'm considering going back to the original API There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not overthink this one. We can replace this function later and focus on other aspects such as a stable intermediate C/C++ interface, validating the packaging (including in Nixpkgs).
You could return a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've decided to spend a small amount of time to explore how a custom type can be added, and it doesn't seem so bad. It's a bit MVP, but it establishes the pattern. |
||
|
||
def test_string(self): | ||
self.assertEqual(nix.eval("a", vars=dict(a="foo")), "foo") | ||
self.assertEqual(nix.callExprString("{ a }: a", arg=dict(a="foo")), "foo") | ||
|
||
def test_bool(self): | ||
self.assertEqual(nix.eval("a", vars=dict(a=True)), True) | ||
self.assertEqual(nix.callExprString("{ a }: a", arg=dict(a=True)), True) | ||
|
||
def test_none(self): | ||
self.assertEqual(nix.eval("a", vars=dict(a=None)), None) | ||
self.assertEqual(nix.callExprString("{ a }: a", arg=dict(a=None)), None) | ||
|
||
def test_ifd(self): | ||
expression = """ | ||
{}: | ||
builtins.readFile (derivation { | ||
name = "test"; | ||
args = [ "-c" "printf \\"%s\\" test > $out" ]; | ||
builder = "/bin/sh"; | ||
system = builtins.currentSystem; | ||
}) | ||
""" | ||
self.assertEqual(nix.eval(expression, vars=dict()), "test") | ||
self.assertEqual(nix.callExprString(expression, arg={}), "test") | ||
|
||
def test_throw(self): | ||
errorString = "hello hi there\ntest" | ||
with self.assertRaises(nix.ThrownNixError) as cm: | ||
nix.eval("throw str", vars=dict(str=errorString)) | ||
nix.callExprString("{ str }: throw str", arg=dict(str=errorString)) | ||
self.assertEqual(cm.exception.args[0], errorString) | ||
|
||
def test_syntax_error(self): | ||
with self.assertRaises(nix.NixError) as cm: | ||
nix.eval("{") | ||
nix.callExprString("{", arg={}) | ||
|
||
def test_GIL_case(self): | ||
with self.assertRaises(nix.ThrownNixError) as cm: | ||
nix.eval("{ a = throw \"nope\"; }") | ||
nix.callExprString("{}: { a = throw \"nope\"; }", arg={}) | ||
self.assertEqual(cm.exception.args[0], "nope") | ||
|
||
def test_infinity(self): | ||
with self.assertRaises(nix.NixError): | ||
nix.eval("let x = { inherit x; }; in x") | ||
nix.callExprString("{}: let x = { inherit x; }; in x", arg={}) | ||
|
||
def test_null_expression(self): | ||
# Null characters should be allowed in expressions, even if they aren't | ||
# very useful really, though at least null's should be supported in | ||
# strings in the future https://github.com/NixOS/nix/issues/1307) | ||
self.assertEqual(nix.eval("\"ab\x00cd\""), "ab") | ||
self.assertEqual(nix.callExprString("{}: \"ab\x00cd\"", arg={}), "ab") | ||
|
||
def test_throw_null(self): | ||
with self.assertRaises(nix.ThrownNixError) as cm: | ||
nix.eval("throw \"hello\x00there\"") | ||
nix.callExprString("{}: throw \"hello\x00there\"", arg={}) | ||
self.assertEqual(cm.exception.args[0], "hello") | ||
|
||
def test_booleans(self): | ||
self.assertIs(nix.eval("assert a == true; a", vars=dict(a=True)), True) | ||
self.assertIs(nix.eval("assert a == false; a", vars=dict(a=False)), False) | ||
self.assertIs(nix.callExprString("{ a }: assert a == true; a", arg=dict(a=True)), True) | ||
self.assertIs(nix.callExprString("{ a }: assert a == false; a", arg=dict(a=False)), False) | ||
|
||
def test_null(self): | ||
self.assertIs(nix.eval("assert a == null; a", vars=dict(a=None)), None) | ||
self.assertIs(nix.callExprString("{ a }: assert a == null; a", arg=dict(a=None)), None) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating an
EvalState
for each call is wasteful and somewhat risky, because that's a less frequently used code path. While I would like to push the envelope on that, it's perhaps not the right to do that.See tweag#17 for a global EvalState solution.