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

Hide warnings #1039

Merged
merged 2 commits into from
Dec 15, 2024
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
23 changes: 23 additions & 0 deletions bindings/python/dlite-misc-python.i
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,29 @@ class errctl():
silent = errctl(hide=True)
"""Context manager for a silent code block. Same as `errctl(hide=True)`."""

class HideDLiteWarnings():
"""Context manager for hiding warnings.

Arguments:
hide: If true, hide warnings if `pattern` is None or `pattern`
matches the warning message.
If false, hide warnings if `pattern` is given and don't
match the warning message.
pattern: Optional glob pattern matching the warning message.

"""
def __init__(self, hide=True, pattern=None):
self.hide = int(hide)
self.pattern = pattern

def __enter__(self):
self._oldstate = get_warnings_hide()
set_warnings_hide(self.hide, self.pattern)

def __exit__(self, *exc):
set_warnings_hide(*self._oldstate)


# A set for keeping track of already issued deprecation warnings
_deprecation_warning_record = set()

Expand Down
12 changes: 11 additions & 1 deletion bindings/python/dlite-misc.i
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
return 0;
}


%}

%include <stdint.i>
Expand Down Expand Up @@ -242,6 +241,17 @@ void _dlite_err_mask_set(int64_t mask);
void errcheck(void);


%feature("docstring", "\
Return a list with the `[hide, pattern]` parameters for controlling whether
warnings are shown.
") dlite_get_warnings_hide;
int dlite_get_warnings_hide(const char **ARGOUT);

%feature("docstring", "Sets parameters controlling whether to hide warnings.")
dlite_set_warnings_hide;
void dlite_set_warnings_hide(int hide, char *pattern=NULL);


/* ------------------------------
* Expose other utility functions
* ------------------------------ */
Expand Down
18 changes: 18 additions & 0 deletions bindings/python/dlite-python.i
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,24 @@ PyObject *dlite_run_file(const char *path, PyObject *globals, PyObject *locals)
* Argout typemaps
* --------------- */

/* Argout string */
/* Assumes that *ARGOUT is const buffer owned by the wrapped function */
%typemap("doc") (const char **ARGOUT) "string"
%typemap(in,numinputs=0) (const char **ARGOUT) (char *tmp=NULL) {
$1 = &tmp;
}
%typemap(argout) (const char **ARGOUT) {
PyObject *argout;
if (tmp$argnum) {
argout = PyUnicode_FromString(tmp$argnum);
} else {
argout = Py_None;
Py_INCREF(argout);
}
$result = SWIG_Python_AppendOutput($result, argout, 0);
}


/* Argout string */
/* Assumes that *ARGOUT_STRING is malloc()'ed by the wrapped function */
%typemap("doc") (char **ARGOUT_STRING, size_t *LENGTH) "string"
Expand Down
6 changes: 1 addition & 5 deletions bindings/python/tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,8 @@
assert inst1b != inst2

# Cannot add an instance with an existing label
try:
with raises(dlite.DLiteValueError):
coll.add("inst1", inst2)
except dlite.DLiteError:
pass
else:
raise RuntimeError("should not be able to replace an existing instance")

coll.add("inst1", inst2, force=True) # forced replacement
assert coll.get("inst1") == inst2
Expand Down
3 changes: 2 additions & 1 deletion bindings/python/tests/test_collection_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@

# Check that we can load collection from dict
d = json.load(open(indir / "coll.json", "r"))
coll = instance_from_dict(d)
with dlite.HideDLiteWarnings():
coll = instance_from_dict(d)
assert coll.nrelations == 6
20 changes: 14 additions & 6 deletions bindings/python/tests/test_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
dlite.storage_path.append(indir / "*.json")
dlite.storage_path.append(entitydir / "*.json")

# Hide warnings
dlite.set_warnings_hide(
True, "Warning: Could not load the following Python plugins:*"
)

# Load metadata (i.e. an instance of meta-metadata) from url
myentity = Instance.from_url(f"json://{entitydir}/MyEntity.json")
print(myentity.uuid)
#print(myentity.uuid)

# Check some properties of the entity
assert myentity.uuid == "a0e63529-3397-5c4f-a56c-14bf07ecc219"
Expand Down Expand Up @@ -74,12 +78,13 @@


# Print the value of all properties
for i in range(len(inst)):
print("prop%d:" % i, inst[i])
# for i in range(len(inst)):
# print("prop%d:" % i, inst[i])

# String representation (as json)
# print(inst)


# Check save and load
inst.save(f"json://{outdir}/test_entity_inst.json?mode=w")
inst2 = Instance.from_url(f"json://{outdir}/test_entity_inst.json")
Expand Down Expand Up @@ -115,7 +120,8 @@
del inst2

# Make sure we fail with an exception for pathetic cases
with raises(dlite.DLiteStorageOpenError):
# FIXME: a part of the error message is not hidden...
with raises(dlite.DLiteError):
Instance.from_location("json", "/", "mode=r")

with raises(dlite.DLiteStorageLoadError):
Expand Down Expand Up @@ -156,7 +162,8 @@

# Check pickling
s = pickle.dumps(inst)
inst3 = pickle.loads(s)
with dlite.HideDLiteWarnings():
inst3 = pickle.loads(s)

dim = Dimension("N")

Expand Down Expand Up @@ -235,7 +242,8 @@
except ImportError:
pass
else:
inst.save(f"yaml://{outdir}/test_entity.yaml?mode=w")
with dlite.HideDLiteWarnings():
inst.save(f"yaml://{outdir}/test_entity.yaml?mode=w")


# Test metadata
Expand Down
8 changes: 4 additions & 4 deletions bindings/python/tests/test_jstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
# Test format_dict(), dimension as list of numbers - need metadata
js = dlite.JStore()
js.load_dict(D1)
meta = js.get()
with dlite.HideDLiteWarnings():
meta = js.get()
assert dlite.format_dict(d3, soft7=True, single=True) == d1
assert dlite.format_dict(d3, soft7=False, single=True) == d2

Expand Down Expand Up @@ -200,9 +201,8 @@
assert len(dct) == 2




key1 = next(js.get_ids())
# d1 = js.get_dict(key1)
s1 = js.get_json(key1)
inst1 = js.get(key1)
with dlite.HideDLiteWarnings():
inst1 = js.get(key1)
3 changes: 2 additions & 1 deletion bindings/python/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
print("No DLite error message is printed to screen:")
try:
with dlite.errctl(hide=(dlite.DLiteStorageOpenError, dlite.DLiteError)):
dlite.Instance.from_location("-", "__non-existing__")
with dlite.HideDLiteWarnings():
dlite.Instance.from_location("-", "__non-existing__")
except dlite.DLiteStorageOpenError:
pass

Expand Down
88 changes: 80 additions & 8 deletions src/dlite-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "utils/session.h"
#include "utils/rng.h"
#include "utils/uri_encode.h"
#include "utils/globmatch.h"
#include "getuuid.h"
#include "dlite.h"
#include "dlite-macros.h"
Expand Down Expand Up @@ -487,8 +488,13 @@ int dlite_add_dll_path(void)

/* Local state for this module. */
typedef struct {
int in_atexit;
int finalizing;
int in_atexit; // whether we are in atexit()
int finalizing; // whether dlite is finalising
int warnings_hide; // whether to hide warnings
char *warnings_pattern; // If given and `warnings_hide` is true, hide
// warnings matching the glob pattern. Otherwise,
// if `warnings_hide` is false, show only
// warnings matching the glob pattern.
} Locals;


Expand All @@ -501,6 +507,7 @@ Locals *_locals=NULL;
/* Free variables in local state. */
static void free_locals()
{
if (_locals && _locals->warnings_pattern) free(_locals->warnings_pattern);
_locals = NULL;
}

Expand Down Expand Up @@ -561,6 +568,47 @@ void dlite_globals_set(DLiteGlobals *globals_handler)
err_set_state(g);
}

/*
Return parameters controlling whether warnings should be hidden.

See dlite_set_warnings_hide() for a description of these parameters.

If `*pattern` is not NULL, it is assigned to a static pointer to
`warnings_pattern` (owned by DLite).

Returns `warnings_hide`.
*/
int dlite_get_warnings_hide(const char **pattern)
{
Locals *locals = get_locals();
if (pattern) *pattern = locals->warnings_pattern;
return locals->warnings_hide;
}

/*
Set parameters controlling whether warnings should be hidden.

Warning parameters:
- `warnings_hide`: whether to hide warnings (see below).
- `warnings_pattern`: glob pattern matching the warning message.

If `warnings_pattern` is NULL, warnings are hidden if `warnings_hide`
is non-zero.

If `warnings_pattern` is given, then warnings are hidden if:
- `warnings_pattern` match the warning message and `warnings_hide` is
non-zero.
- `warnings_pattern` don't match the warning message and `warnings_hide`
is zero.
*/
void dlite_set_warnings_hide(int hide, char *pattern)
{
Locals *locals = get_locals();
locals->warnings_hide = hide;
if (locals->warnings_pattern) free(locals->warnings_pattern);
locals->warnings_pattern = (pattern) ? strdup(pattern) : NULL;
}


/* Error handler for DLite.

Expand All @@ -569,15 +617,39 @@ void dlite_globals_set(DLiteGlobals *globals_handler)
*/
static void dlite_err_handler(const ErrRecord *record)
{
Locals *locals = get_locals();

if (getenv("DLITE_DEBUG")
#ifdef WITH_PYTHON
if (record->level != errLevelError ||
getenv("DLITE_PYDEBUG") ||
!dlite_err_ignored_get(record->eval))
|| getenv("DLITE_PYDEBUG")
#endif
) {
err_default_handler(record);
#else /* WITH_PYTHON */
if (!dlite_err_ignored_get(record->eval))
return;
}

switch (record->level) {
case errLevelSuccess:
break;
case errLevelWarn:
if (locals->warnings_pattern) {
int match = !globmatch(locals->warnings_pattern, record->msg);
if ((match && !locals->warnings_hide) ||
(!match && locals->warnings_hide))
err_default_handler(record);
} else if (!locals->warnings_hide) {
err_default_handler(record);
}
break;
case errLevelError:
if (!dlite_err_ignored_get(record->eval))
err_default_handler(record);
break;
case errLevelException:
case errLevelFatal:
err_default_handler(record);
#endif
break;
}
}

/* dlite_errname() with correct call signature */
Expand Down
37 changes: 37 additions & 0 deletions src/dlite-misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,43 @@ void dlite_globals_set_atexit(void);
/** @} */


/**
@name Functions controlling whether to hide warnings

Warning parameters:
- `warnings_hide`: whether to hide warnings (see below).
- `warnings_pattern`: glob pattern matching the warning message.

If `warnings_pattern` is NULL, warnings are hidden if `warnings_hide`
is non-zero.

If `warnings_pattern` is not NULL, then warnings are hidden if:
- `warnings_pattern` match the warning message and `warnings_hide` is
non-zero.
- `warnings_pattern` don't match the warning message and `warnings_hide`
is zero.
@{
*/

/**
Return parameters controlling whether warnings should be hidden.

If `*pattern` is not NULL, it is assigned to a static pointer to
`warnings_pattern` (owned by DLite).

Returns `warnings_hide`.
*/

int dlite_get_warnings_hide(const char **pattern);

/**
Set parameters controlling whether warnings should be hidden.
*/
void dlite_set_warnings_hide(int hide, char *pattern);

/** @} */


/**
@name Wrappers around error functions
The `DLITE_NOERR()` and `DLITE_NOERR_END` macros are intended to
Expand Down
8 changes: 8 additions & 0 deletions src/utils/tests/test_globmatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ MU_TEST(test_globmatch)
{
mu_check(0 == globmatch("", ""));
mu_check(1 == globmatch("?", ""));
mu_check(0 == globmatch("?", "a"));
mu_check(0 == globmatch("*", ""));
mu_check(0 == globmatch("?etc*", "/etc/fstab"));
mu_check(0 == globmatch("*etc*", "/etc/fstab"));
mu_check(1 == globmatch("etc*", "/etc/fstab"));
mu_check(0 == globmatch("*tc*", "/etc/fstab"));
mu_check(1 == globmatch("*x*", "/etc/fstab"));
mu_check(0 == globmatch("/[a-f]tc*", "/etc/fstab"));
mu_check(0 == globmatch("[^A-Za-z]etc*", "/etc/fstab"));
mu_check(1 == globmatch("[A-Za-z]etc*", "/etc/fstab"));
mu_check(0 == globmatch("\\/etc*", "/etc/fstab"));
mu_check(0 == globmatch("?etc*tab", "/etc/fstab"));
mu_check(0 == globmatch("*", "a\nstring\nover multiple\nlines...\n"));
mu_check(1 == globmatch("*.", "a\nstring\nover multiple\nlines...\n"));
mu_check(0 == globmatch("*", "Warning: Behavior change `storageQuery` is not configured. It will be enabled by default from v0.6.0. See https://sintef.github.io/dlite/user_guide/configure_behavior_changes.html for more info."));
}

/***********************************************************************/
Expand Down
Loading