diff --git a/python/src/eval.cc b/python/src/eval.cc index ec15d0c0eb3..e95f7c88b96 100644 --- a/python/src/eval.cc +++ b/python/src/eval.cc @@ -9,53 +9,53 @@ namespace pythonnix { -const char *currentExceptionTypeName() { - int status; - auto res = abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, - 0, &status); - return res ? res : "(null)"; +const char * currentExceptionTypeName() +{ + int status; + auto res = abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status); + return res ? res : "(null)"; } -static PyObject *_eval(const char *expression, PyObject *vars) { - nix::Strings storePath; - nix::EvalState state(storePath, nix::openStore()); +static PyObject * _eval(const char * expression, PyObject * vars) +{ + nix::Strings storePath; + nix::EvalState state(storePath, nix::openStore()); - nix::Env *env = nullptr; - auto staticEnv = pythonToNixEnv(state, vars, &env); - if (!staticEnv) { - return nullptr; - } - auto staticEnvPointer = std::make_shared(*staticEnv); + nix::Env * env = nullptr; + auto staticEnv = pythonToNixEnv(state, vars, &env); + if (!staticEnv) { + return nullptr; + } + auto staticEnvPointer = std::make_shared(*staticEnv); - auto e = state.parseExprFromString(expression, ".", staticEnvPointer); - nix::Value v; - e->eval(state, *env, v); + auto e = state.parseExprFromString(expression, ".", staticEnvPointer); + nix::Value v; + e->eval(state, *env, v); - state.forceValueDeep(v); + state.forceValueDeep(v); - nix::PathSet context; - return nixToPythonObject(state, v, context); + nix::PathSet context; + return nixToPythonObject(state, v, context); } -PyObject *eval(PyObject *self, PyObject *args, PyObject *keywds) { - const char *expression = nullptr; - PyObject *vars = nullptr; - - const char *kwlist[] = {"expression", "vars", nullptr}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O!", - const_cast(kwlist), &expression, - &PyDict_Type, &vars)) { - return nullptr; - } - - try { - return _eval(expression, vars); - } catch (nix::Error &e) { - return PyErr_Format(NixError, "%s", e.what()); - } catch (...) { - return PyErr_Format(NixError, "unexpected C++ exception: '%s'", - currentExceptionTypeName()); - } +PyObject * eval(PyObject * self, PyObject * args, PyObject * keywds) +{ + const char * expression = nullptr; + PyObject * vars = nullptr; + + const char * kwlist[] = {"expression", "vars", nullptr}; + + if (!PyArg_ParseTupleAndKeywords( + args, keywds, "s|O!", const_cast(kwlist), &expression, &PyDict_Type, &vars)) { + return nullptr; + } + + try { + return _eval(expression, vars); + } catch (nix::Error & e) { + return PyErr_Format(NixError, "%s", e.what()); + } catch (...) { + return PyErr_Format(NixError, "unexpected C++ exception: '%s'", currentExceptionTypeName()); + } } } // namespace pythonnix diff --git a/python/src/internal/errors.hh b/python/src/internal/errors.hh index 86d0cf577bc..a4f6bd81e0b 100644 --- a/python/src/internal/errors.hh +++ b/python/src/internal/errors.hh @@ -4,5 +4,5 @@ namespace pythonnix { -extern PyObject *NixError; +extern PyObject * NixError; } diff --git a/python/src/internal/eval.hh b/python/src/internal/eval.hh index dc6fe1f7580..878b82ff643 100644 --- a/python/src/internal/eval.hh +++ b/python/src/internal/eval.hh @@ -4,5 +4,5 @@ namespace pythonnix { -PyObject *eval(PyObject *self, PyObject *args, PyObject *kwdict); +PyObject * eval(PyObject * self, PyObject * args, PyObject * kwdict); } diff --git a/python/src/internal/nix-to-python.hh b/python/src/internal/nix-to-python.hh index a6266fa90f3..bfcc8bf22ba 100644 --- a/python/src/internal/nix-to-python.hh +++ b/python/src/internal/nix-to-python.hh @@ -8,6 +8,5 @@ namespace pythonnix { -PyObject *nixToPythonObject(nix::EvalState &state, nix::Value &v, - nix::PathSet &context); +PyObject * nixToPythonObject(nix::EvalState & state, nix::Value & v, nix::PathSet & context); } // namespace pythonnix diff --git a/python/src/internal/ptr.hh b/python/src/internal/ptr.hh index 16558772848..5ca073de283 100644 --- a/python/src/internal/ptr.hh +++ b/python/src/internal/ptr.hh @@ -5,8 +5,12 @@ namespace pythonnix { -struct PyObjectDeleter { - void operator()(PyObject *const obj) { Py_DECREF(obj); } +struct PyObjectDeleter +{ + void operator()(PyObject * const obj) + { + Py_DECREF(obj); + } }; typedef std::unique_ptr PyObjPtr; diff --git a/python/src/internal/python-to-nix.hh b/python/src/internal/python-to-nix.hh index db14b7f7533..3137336e964 100644 --- a/python/src/internal/python-to-nix.hh +++ b/python/src/internal/python-to-nix.hh @@ -8,8 +8,7 @@ namespace pythonnix { -nix::Value *pythonToNixValue(nix::EvalState &state, PyObject *obj); +nix::Value * pythonToNixValue(nix::EvalState & state, PyObject * obj); -std::optional pythonToNixEnv(nix::EvalState &state, - PyObject *vars, nix::Env **env); +std::optional pythonToNixEnv(nix::EvalState & state, PyObject * vars, nix::Env ** env); } // namespace pythonnix diff --git a/python/src/nix-to-python.cc b/python/src/nix-to-python.cc index 63793f56ac9..4527587709d 100644 --- a/python/src/nix-to-python.cc +++ b/python/src/nix-to-python.cc @@ -6,84 +6,83 @@ namespace pythonnix { -PyObject *nixToPythonObject(nix::EvalState &state, nix::Value &v, - nix::PathSet &context) { - switch (v.type()) { - case nix::nInt: - return PyLong_FromLong(v.integer); +PyObject * nixToPythonObject(nix::EvalState & state, nix::Value & v, nix::PathSet & context) +{ + switch (v.type()) { + case nix::nInt: + return PyLong_FromLong(v.integer); - case nix::nBool: - if (v.boolean) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } - case nix::nString: - copyContext(v, context); - return PyUnicode_FromString(v.string.s); + case nix::nBool: + if (v.boolean) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } + case nix::nString: + copyContext(v, context); + return PyUnicode_FromString(v.string.s); - case nix::nPath: { - auto p = state.copyPathToStore(context, v.path).to_string(); - return PyUnicode_FromStringAndSize(p.data(), p.length()); - } + case nix::nPath: { + auto p = state.copyPathToStore(context, v.path).to_string(); + return PyUnicode_FromStringAndSize(p.data(), p.length()); + } - case nix::nNull: - Py_RETURN_NONE; + case nix::nNull: + Py_RETURN_NONE; - case nix::nAttrs: { - auto i = v.attrs->find(state.sOutPath); - if (i == v.attrs->end()) { - PyObjPtr dict(PyDict_New()); - if (!dict) { - return (PyObject *)nullptr; - } + case nix::nAttrs: { + auto i = v.attrs->find(state.sOutPath); + if (i == v.attrs->end()) { + PyObjPtr dict(PyDict_New()); + if (!dict) { + return (PyObject *) nullptr; + } - for (auto &j : *v.attrs) { - const std::string & name = state.symbols[j.name]; - auto value = nixToPythonObject(state, *j.value, context); - if (!value) { - return nullptr; + for (auto & j : *v.attrs) { + const std::string & name = state.symbols[j.name]; + auto value = nixToPythonObject(state, *j.value, context); + if (!value) { + return nullptr; + } + PyDict_SetItemString(dict.get(), name.c_str(), value); + } + return dict.release(); + } else { + return nixToPythonObject(state, *i->value, context); } - PyDict_SetItemString(dict.get(), name.c_str(), value); - } - return dict.release(); - } else { - return nixToPythonObject(state, *i->value, context); } - } - case nix::nList: { - PyObjPtr list(PyList_New(v.listSize())); - if (!list) { - return (PyObject *)nullptr; - } + case nix::nList: { + PyObjPtr list(PyList_New(v.listSize())); + if (!list) { + return (PyObject *) nullptr; + } - for (unsigned int n = 0; n < v.listSize(); ++n) { - auto value = nixToPythonObject(state, *v.listElems()[n], context); - if (!value) { - return nullptr; - } - PyList_SET_ITEM(list.get(), n, value); + for (unsigned int n = 0; n < v.listSize(); ++n) { + auto value = nixToPythonObject(state, *v.listElems()[n], context); + if (!value) { + return nullptr; + } + PyList_SET_ITEM(list.get(), n, value); + } + return list.release(); } - return list.release(); - } - case nix::nExternal: - return PyUnicode_FromString(""); + case nix::nExternal: + return PyUnicode_FromString(""); - case nix::nThunk: - return PyUnicode_FromString(""); + case nix::nThunk: + return PyUnicode_FromString(""); - case nix::nFunction: - return PyUnicode_FromString(""); + case nix::nFunction: + return PyUnicode_FromString(""); - case nix::nFloat: - return PyFloat_FromDouble(v.fpoint); + case nix::nFloat: + return PyFloat_FromDouble(v.fpoint); - default: - PyErr_Format(NixError, "cannot convert nix type '%s' to a python object", - showType(v).c_str()); - return nullptr; - } + default: + PyErr_Format(NixError, "cannot convert nix type '%s' to a python object", showType(v).c_str()); + return nullptr; + } } } // namespace pythonnix diff --git a/python/src/python-module.cc b/python/src/python-module.cc index 25806929bdb..f255abc0f9c 100644 --- a/python/src/python-module.cc +++ b/python/src/python-module.cc @@ -13,12 +13,10 @@ namespace pythonnix { #define _public_ __attribute__((visibility("default"))) -PyObject *NixError = nullptr; +PyObject * NixError = nullptr; -static PyMethodDef NixMethods[] = {{"eval", (PyCFunction)eval, - METH_VARARGS | METH_KEYWORDS, - "Eval nix expression"}, - {NULL, NULL, 0, NULL}}; +static PyMethodDef NixMethods[] = { + {"eval", (PyCFunction) eval, METH_VARARGS | METH_KEYWORDS, "Eval nix expression"}, {NULL, NULL, 0, NULL}}; static struct PyModuleDef nixmodule = { PyModuleDef_HEAD_INIT, "nix", "Nix expression bindings", @@ -26,36 +24,38 @@ static struct PyModuleDef nixmodule = { or -1 if the module keeps state in global variables. */ NixMethods}; -extern "C" _public_ PyObject *PyInit_nix(void) { - // By default, Nix sets the build-hook to be "$(readlink /proc/self/exe) __build-remote", expecting the current binary to be Nix itself. - // But when we call the Nix library from Python this isn't the case, the current binary is Python then - // So we need to change this default, pointing it to the Nix binary instead - nix::settings.buildHook = nix::settings.nixBinDir + "/nix __build-remote"; - // And by setting buildHook before calling initNix, we can override the defaults without overriding the user-provided options from the config files - nix::initNix(); - nix::initGC(); - - PyObjPtr m(PyModule_Create(&nixmodule)); - - if (!m) { - return nullptr; - } - - NixError = PyErr_NewExceptionWithDoc( - "nix.NixError", /* char *name */ - "Base exception class for the nix module.", /* char *doc */ - NULL, /* PyObject *base */ - NULL /* PyObject *dict */ - ); - - if (!NixError) { - return nullptr; - } - - if (PyModule_AddObject(m.get(), "NixError", NixError) == -1) { - return nullptr; - } - - return m.release(); +extern "C" _public_ PyObject * PyInit_nix(void) +{ + // By default, Nix sets the build-hook to be "$(readlink /proc/self/exe) __build-remote", expecting the current + // binary to be Nix itself. But when we call the Nix library from Python this isn't the case, the current binary is + // Python then So we need to change this default, pointing it to the Nix binary instead + nix::settings.buildHook = nix::settings.nixBinDir + "/nix __build-remote"; + // And by setting buildHook before calling initNix, we can override the defaults without overriding the + // user-provided options from the config files + nix::initNix(); + nix::initGC(); + + PyObjPtr m(PyModule_Create(&nixmodule)); + + if (!m) { + return nullptr; + } + + NixError = PyErr_NewExceptionWithDoc( + "nix.NixError", /* char *name */ + "Base exception class for the nix module.", /* char *doc */ + NULL, /* PyObject *base */ + NULL /* PyObject *dict */ + ); + + if (!NixError) { + return nullptr; + } + + if (PyModule_AddObject(m.get(), "NixError", NixError) == -1) { + return nullptr; + } + + return m.release(); } } // namespace pythonnix diff --git a/python/src/python-to-nix.cc b/python/src/python-to-nix.cc index f6326eef488..6f52187ab22 100644 --- a/python/src/python-to-nix.cc +++ b/python/src/python-to-nix.cc @@ -8,153 +8,157 @@ namespace pythonnix { -static const char *checkNullByte(const char *str, const Py_ssize_t size) { - for (Py_ssize_t i = 0; i < size; i++) { - if (str[0] == '\0') { - PyErr_Format(NixError, "invalid character: nix strings are not allowed " - "to contain null bytes"); - return nullptr; +static const char * checkNullByte(const char * str, const Py_ssize_t size) +{ + for (Py_ssize_t i = 0; i < size; i++) { + if (str[0] == '\0') { + PyErr_Format( + NixError, + "invalid character: nix strings are not allowed " + "to contain null bytes"); + return nullptr; + } } - } - return str; + return str; } -static const char *checkAttrKey(PyObject *obj) { - Py_ssize_t size = 0; - - if (!PyUnicode_Check(obj)) { - PyObjPtr typeName(PyObject_Str(PyObject_Type(obj))); - if (!typeName) { - return nullptr; +static const char * checkAttrKey(PyObject * obj) +{ + Py_ssize_t size = 0; + + if (!PyUnicode_Check(obj)) { + PyObjPtr typeName(PyObject_Str(PyObject_Type(obj))); + if (!typeName) { + return nullptr; + } + auto utf8 = PyUnicode_AsUTF8AndSize(typeName.get(), &size); + if (!utf8) { + return nullptr; + } + PyErr_Format(NixError, "key of nix attrsets must be strings, got type: %s", utf8); + return nullptr; } - auto utf8 = PyUnicode_AsUTF8AndSize(typeName.get(), &size); + + auto utf8 = PyUnicode_AsUTF8AndSize(obj, &size); if (!utf8) { - return nullptr; + return nullptr; } - PyErr_Format(NixError, "key of nix attrsets must be strings, got type: %s", - utf8); - return nullptr; - } - - auto utf8 = PyUnicode_AsUTF8AndSize(obj, &size); - if (!utf8) { - return nullptr; - } - return checkNullByte(utf8, size); + return checkNullByte(utf8, size); } -static std::optional dictToAttrSet(PyObject *obj, - nix::EvalState &state) { - PyObject *key = nullptr, *val = nullptr; - Py_ssize_t pos = 0; - - nix::ValueMap attrs; - while (PyDict_Next(obj, &pos, &key, &val)) { - auto name = checkAttrKey(key); - if (!name) { - return {}; - } - - auto attrVal = pythonToNixValue(state, val); - if (!attrVal) { - return {}; +static std::optional dictToAttrSet(PyObject * obj, nix::EvalState & state) +{ + PyObject *key = nullptr, *val = nullptr; + Py_ssize_t pos = 0; + + nix::ValueMap attrs; + while (PyDict_Next(obj, &pos, &key, &val)) { + auto name = checkAttrKey(key); + if (!name) { + return {}; + } + + auto attrVal = pythonToNixValue(state, val); + if (!attrVal) { + return {}; + } + attrs[state.symbols.create(name)] = attrVal; } - attrs[state.symbols.create(name)] = attrVal; - } - return attrs; + return attrs; } -nix::Value *pythonToNixValue(nix::EvalState &state, PyObject *obj) { - auto v = state.allocValue(); - - if (obj == Py_True && obj == Py_False) { - v->mkBool(obj == Py_True); - } else if (obj == Py_None) { - v->mkNull(); - } else if (PyBytes_Check(obj)) { - auto str = checkNullByte(PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj)); - if (!str) { - return nullptr; - } - - v->mkString(str); - } else if (PyUnicode_Check(obj)) { - Py_ssize_t size; - const char *utf8 = PyUnicode_AsUTF8AndSize(obj, &size); - auto str = checkNullByte(utf8, size); - if (!str) { - return nullptr; +nix::Value * pythonToNixValue(nix::EvalState & state, PyObject * obj) +{ + auto v = state.allocValue(); + + if (obj == Py_True && obj == Py_False) { + v->mkBool(obj == Py_True); + } else if (obj == Py_None) { + v->mkNull(); + } else if (PyBytes_Check(obj)) { + auto str = checkNullByte(PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj)); + if (!str) { + return nullptr; + } + + v->mkString(str); + } else if (PyUnicode_Check(obj)) { + Py_ssize_t size; + const char * utf8 = PyUnicode_AsUTF8AndSize(obj, &size); + auto str = checkNullByte(utf8, size); + if (!str) { + return nullptr; + } + + v->mkString(utf8); + } else if (PyFloat_Check(obj)) { + v->mkFloat(PyFloat_AS_DOUBLE(obj)); + } else if (PyLong_Check(obj)) { + v->mkInt(PyLong_AsLong(obj)); + } else if (PyList_Check(obj)) { + v->mkList(PyList_GET_SIZE(obj)); + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(obj); i++) { + auto val = pythonToNixValue(state, PyList_GET_ITEM(obj, i)); + if (!val) { + return nullptr; + } + v->listElems()[i] = val; + } + } else if (PyTuple_Check(obj)) { + v->mkList(PyTuple_GET_SIZE(obj)); + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(obj); i++) { + auto val = pythonToNixValue(state, PyTuple_GET_ITEM(obj, i)); + if (!val) { + return nullptr; + } + v->listElems()[i] = val; + } + } else if (PyDict_Check(obj)) { + auto attrs = dictToAttrSet(obj, state); + if (!attrs) { + return nullptr; + } + auto attrsValue = attrs.value(); + auto bindings = state.buildBindings(attrsValue.size()); + for (auto & attr : attrsValue) { + bindings.insert(attr.first, attr.second); + } + v->mkAttrs(bindings); } - - v->mkString(utf8); - } else if (PyFloat_Check(obj)) { - v->mkFloat(PyFloat_AS_DOUBLE(obj)); - } else if (PyLong_Check(obj)) { - v->mkInt(PyLong_AsLong(obj)); - } else if (PyList_Check(obj)) { - v->mkList(PyList_GET_SIZE(obj)); - for (Py_ssize_t i = 0; i < PyList_GET_SIZE(obj); i++) { - auto val = pythonToNixValue(state, PyList_GET_ITEM(obj, i)); - if (!val) { - return nullptr; - } - v->listElems()[i] = val; - } - } else if (PyTuple_Check(obj)) { - v->mkList(PyTuple_GET_SIZE(obj)); - for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(obj); i++) { - auto val = pythonToNixValue(state, PyTuple_GET_ITEM(obj, i)); - if (!val) { - return nullptr; - } - v->listElems()[i] = val; - } - } else if (PyDict_Check(obj)) { - auto attrs = dictToAttrSet(obj, state); - if (!attrs) { - return nullptr; - } - auto attrsValue = attrs.value(); - auto bindings = state.buildBindings(attrsValue.size()); - for (auto &attr : attrsValue) { - bindings.insert(attr.first, attr.second); - } - v->mkAttrs(bindings); - } - return v; + return v; } -std::optional pythonToNixEnv(nix::EvalState &state, - PyObject *vars, nix::Env **env) { - Py_ssize_t pos = 0; - PyObject *key = nullptr, *val = nullptr; +std::optional pythonToNixEnv(nix::EvalState & state, PyObject * vars, nix::Env ** env) +{ + Py_ssize_t pos = 0; + PyObject *key = nullptr, *val = nullptr; - *env = &state.allocEnv(vars ? PyDict_Size(vars) : 0); - (*env)->up = &state.baseEnv; + *env = &state.allocEnv(vars ? PyDict_Size(vars) : 0); + (*env)->up = &state.baseEnv; - nix::StaticEnv staticEnv(false, state.staticBaseEnv.get()); + nix::StaticEnv staticEnv(false, state.staticBaseEnv.get()); - if (!vars) { - return staticEnv; - } - - auto displ = 0; - while (PyDict_Next(vars, &pos, &key, &val)) { - auto name = checkAttrKey(key); - if (!name) { - return {}; + if (!vars) { + return staticEnv; } - auto attrVal = pythonToNixValue(state, val); - if (!attrVal) { - return {}; + auto displ = 0; + while (PyDict_Next(vars, &pos, &key, &val)) { + auto name = checkAttrKey(key); + if (!name) { + return {}; + } + + auto attrVal = pythonToNixValue(state, val); + if (!attrVal) { + return {}; + } + staticEnv.vars.emplace_back(state.symbols.create(name), displ); + (*env)->values[displ++] = attrVal; } - staticEnv.vars.emplace_back(state.symbols.create(name), displ); - (*env)->values[displ++] = attrVal; - } - return staticEnv; + return staticEnv; } } // namespace pythonnix