Skip to content

Commit

Permalink
Merge branch 'master' into fix-docs-errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jesper-friis authored Oct 30, 2024
2 parents f5d7caa + dde498f commit c8aace3
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 72 deletions.
13 changes: 11 additions & 2 deletions bindings/python/scripts/dlite-validate
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import json
import re
from pathlib import Path

import dlite


def parse(url, driver=None, options="mode=r", id=None):
"""Loads an instance from storage.
Expand All @@ -22,6 +20,8 @@ def parse(url, driver=None, options="mode=r", id=None):
Returns:
A new instance.
"""
import dlite

loc = url.split("#", 1)[0].split("?",1)[0]
if driver is None:
driver = Path(loc).suffix.lstrip('.').lower()
Expand Down Expand Up @@ -102,6 +102,15 @@ def main():

args = parser.parse_args()

if not args.debug:
# Turn off DLite warnings about behavior changes
import __main__
__main__.DLITE_BEHAVIOR = True

# Delay importing dlite to after options are processed such that it is
# possible to configure DLite by settings variables in __main__.
import dlite

for path in args.storage_path:
dlite.storage_path.append(Path(path).resolve())

Expand Down
7 changes: 7 additions & 0 deletions src/config-paths.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,12 @@
#define dlite_TEMPLATES "@dlite_TEMPLATES@"
#define dlite_STORAGES "@dlite_STORAGES@"

/* dlite-pyembed.c does not imports config.h to avoid conflicts with Python .h
Include configurations needed by dlite-pyembed.c here */
#cmakedefine HAVE_SETENV
#cmakedefine HAVE__PUTENV_S
#cmakedefine HAVE_UNSETENV



#endif /* _DLITE_CONFIG_PATHS_H */
2 changes: 1 addition & 1 deletion src/dlite-behavior.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ int dlite_behavior_get(const char *name)
const char *ver = dlite_get_version(); // current version
b->value = (strcmp_semver(ver, b->version_new) >= 0) ? 1 : 0;

dlite_warnx("Behavior `%s` is not configured. "
dlite_warnx("Behavior change `%s` is not configured. "
"It will be enabled by default from v%s. "
"See https://sintef.github.io/dlite/user_guide/configure_behavior_changes.html for more info.",
b->name, b->version_new);
Expand Down
172 changes: 104 additions & 68 deletions src/pyembed/dlite-pyembed.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,85 +141,121 @@ void dlite_pyembed_initialise(void)
{
PyembedGlobals *g = get_globals();

if (!g->initialised &&
(!Py_IsInitialized() || !dlite_behavior_get("singleInterpreter"))) {
if (!g->initialised) {
g->initialised = 1;

#if defined(HAVE_SETENV) || defined(HAVE__PUTENV_S)
if (Py_IsInitialized()) {
/* Set environment variables from global variables in Python
starting with "DLITE_" */
PyObject *maindict = dlite_python_maindict();
PyObject *key, *value;
Py_ssize_t pos = 0;

while (PyDict_Next(maindict, &pos, &key, &value)) {
if (PyUnicode_Check(key)) {
const char *ckey = PyUnicode_AsUTF8AndSize(key, NULL);
assert(ckey);
if (strncmp(ckey, "DLITE_", 6) == 0) {
if (PyBool_Check(value)) {
if (PyObject_IsTrue(value)) setenv(ckey, "", 1);
} else if (PyLong_Check(value)) {
long v = PyLong_AsLong(value);
char cval[32];
snprintf(cval, sizeof(cval), "%ld", v);
setenv(ckey, cval, 1);
} else if (PyUnicode_Check(value)) {
const char *cval = PyUnicode_AsUTF8AndSize(value, NULL);
setenv(ckey, cval, 1);
} else {
dlite_warnx("Unsupported type for value of global variable `%s`. "
"Should be bool, str or int.", ckey);
}
}
}
}
}
#endif

if (!Py_IsInitialized() || !dlite_behavior_get("singleInterpreter")) {
/*
Initialise new Python interpreter
/*
Python 3.8 and later implements the new Python
Initialisation Configuration.
Python 3.8 and later implements the new Python
Initialisation Configuration.
More features were added in the following releases,
like `config.safe_path`, which was added in Python 3.11
More features were added in the following releases,
like `config.safe_path`, which was added in Python 3.11
The old Py_SetProgramName() was deprecated in Python 3.11.
The old Py_SetProgramName() was deprecated in Python 3.11.
In DLite, we switch to the new Python Initialisation
Configuration from Python 3.11.
*/
PyObject *sys=NULL, *sys_path=NULL, *path=NULL;
In DLite, we switch to the new Python Initialisation
Configuration from Python 3.11.
*/
PyObject *sys=NULL, *sys_path=NULL, *path=NULL;
#if PY_VERSION_HEX >= 0x030b0000 /* Python >= 3.11 */
/* New Python Initialisation Configuration */
PyStatus status;
PyConfig config;

PyConfig_InitPythonConfig(&config);
config.isolated = 0;
config.safe_path = 0;
config.use_environment = 1;
config.user_site_directory = 1;

/* If dlite is called from a python, reparse arguments to avoid
that they are stripped off... */
if (Py_IsInitialized()) {
int argc=0;
wchar_t **argv=NULL;
Py_GetArgcArgv(&argc, &argv);
config.parse_argv = 1;
status = PyConfig_SetArgv(&config, argc, argv);
if (PyStatus_Exception(status))
FAIL("failed configuring pyembed arguments");
}
/* New Python Initialisation Configuration */
PyStatus status;
PyConfig config;

PyConfig_InitPythonConfig(&config);
config.isolated = 0;
config.safe_path = 0;
config.use_environment = 1;
config.user_site_directory = 1;

/* If dlite is called from a python, reparse arguments to avoid
that they are stripped off... */
if (Py_IsInitialized()) {
int argc=0;
wchar_t **argv=NULL;
Py_GetArgcArgv(&argc, &argv);
config.parse_argv = 1;
status = PyConfig_SetArgv(&config, argc, argv);
if (PyStatus_Exception(status))
FAIL("failed configuring pyembed arguments");
}

status = PyConfig_SetBytesString(&config, &config.program_name, "dlite");
if (PyStatus_Exception(status))
FAIL("failed configuring pyembed program name");
status = PyConfig_SetBytesString(&config, &config.program_name, "dlite");
if (PyStatus_Exception(status))
FAIL("failed configuring pyembed program name");

status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status))
FAIL("failed clearing pyembed config");
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status))
FAIL("failed clearing pyembed config");
#else
/* Old Initialisation */
wchar_t *progname;
/* Old Initialisation */
wchar_t *progname;

Py_Initialize();
Py_Initialize();

if (!(progname = Py_DecodeLocale("dlite", NULL))) {
dlite_err(1, "allocation/decoding failure");
return;
}
Py_SetProgramName(progname);
PyMem_RawFree(progname);
#endif

if (dlite_use_build_root()) {
if (!(sys = PyImport_ImportModule("sys")))
FAIL("cannot import sys");
if (!(sys_path = PyObject_GetAttrString(sys, "path")))
FAIL("cannot access sys.path");
if (!PyList_Check(sys_path))
FAIL("sys.path is not a list");
if (!(path = PyUnicode_FromString(dlite_PYTHONPATH)))
FAIL("cannot create python object for dlite_PYTHONPATH");
if (PyList_Insert(sys_path, 0, path))
FAIL1("cannot insert %s into sys.path", dlite_PYTHONPATH);
}
if (!(progname = Py_DecodeLocale("dlite", NULL))) {
dlite_err(1, "allocation/decoding failure");
return;
}
Py_SetProgramName(progname);
PyMem_RawFree(progname);
#endif

if (dlite_use_build_root()) {
if (!(sys = PyImport_ImportModule("sys")))
FAIL("cannot import sys");
if (!(sys_path = PyObject_GetAttrString(sys, "path")))
FAIL("cannot access sys.path");
if (!PyList_Check(sys_path))
FAIL("sys.path is not a list");
if (!(path = PyUnicode_FromString(dlite_PYTHONPATH)))
FAIL("cannot create python object for dlite_PYTHONPATH");
if (PyList_Insert(sys_path, 0, path))
FAIL1("cannot insert %s into sys.path", dlite_PYTHONPATH);
}

g->initialised = 1;
fail:
Py_XDECREF(sys);
Py_XDECREF(sys_path);
Py_XDECREF(path);
fail:
Py_XDECREF(sys);
Py_XDECREF(sys_path);
Py_XDECREF(path);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/pyembed/dlite-pyembed.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

//#define Py_LIMITED_API 0x03080000
#include <Python.h>

/* Python pulls in a lot of defines that conflicts with utils/config.h */
Expand Down
1 change: 1 addition & 0 deletions src/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ check_symbol_exists(strncasecmp string.h HAVE_STRNCASECMP)
check_symbol_exists(_strnicmp string.h HAVE__STRNICMP)

check_symbol_exists(setenv stdlib.h HAVE_SETENV)
check_symbol_exists(_putenv_s stdlib.h HAVE__PUTENV_S)
check_symbol_exists(unsetenv stdlib.h HAVE_UNSETENV)

check_symbol_exists(realpath stdlib.h HAVE_REALPATH)
Expand Down
13 changes: 13 additions & 0 deletions src/utils/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ typedef int make_iso_compilers_happy;
#endif


/* setenv() - change or add an environment variable */
#ifndef HAVE_SETENV
# ifdef HAVE__PUTENV_S
int setenv(const char *name, const char *value, int overwrite)
{
if (overwrite || getenv(name))
return _putenv(name, value);
return 0;
}
# endif
#endif


/* strdup() - duplicate a string */
#if !defined(HAVE_STRDUP) && !defined(HAVE__STRDUP)
char *strdup(const char *s)
Expand Down
12 changes: 11 additions & 1 deletion src/utils/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,17 @@
#endif

/*
* compat-src/realpath.c
* compat-src/setenv.c
*/

/** setenv() - change or add an environment variable */
#if !defined(HAVE_SETENV) && defined(HAVE__PUTENV_S)
#define HAVE_SETENV
int setenv(const char *name, const char *value, int overwrite);
#endif

/*
* compat/realpath.c
*/

/** realpath() - return the canonicalized absolute pathname */
Expand Down
1 change: 1 addition & 0 deletions src/utils/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#cmakedefine HAVE__STRNICMP

#cmakedefine HAVE_SETENV
#cmakedefine HAVE__PUTENV_S
#cmakedefine HAVE_UNSETENV

#cmakedefine HAVE_REALPATH
Expand Down

0 comments on commit c8aace3

Please sign in to comment.