Skip to content

Fix logging bug, add access to temp_log_options(), and add logging tests. #142

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions cffi/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ enum ly_stmt {
#define LY_LOSTORE ...
#define LY_LOSTORE_LAST ...
int ly_log_options(int);
uint32_t *ly_temp_log_options(uint32_t *);

LY_LOG_LEVEL ly_log_level(LY_LOG_LEVEL);
extern "Python" void lypy_log_cb(LY_LOG_LEVEL, const char *, const char *, const char *, uint64_t);
Expand Down
2 changes: 1 addition & 1 deletion libyang/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
)
from .extension import ExtensionPlugin, LibyangExtensionError
from .keyed_list import KeyedList
from .log import configure_logging
from .log import configure_logging, temp_log_options
from .schema import (
Extension,
ExtensionCompiled,
Expand Down
15 changes: 14 additions & 1 deletion libyang/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
# Copyright (c) 2020 6WIND S.A.
# SPDX-License-Identifier: MIT

from contextlib import contextmanager
import logging

import cffi

from _libyang import ffi, lib
from .util import c2str

Expand All @@ -26,6 +29,16 @@ def get_libyang_level(py_level):
return None


@contextmanager
def temp_log_options(opt: int = 0):
_ffi = cffi.FFI()
opts = _ffi.new("uint32_t *", opt)

lib.ly_temp_log_options(opts)
yield
lib.ly_temp_log_options(ffi.NULL)


@ffi.def_extern(name="lypy_log_cb")
def libyang_c_logging_callback(level, msg, data_path, schema_path, line):
args = [c2str(msg)]
Expand All @@ -38,7 +51,7 @@ def libyang_c_logging_callback(level, msg, data_path, schema_path, line):
args.append(c2str(schema_path))
if line != 0:
fmt += " line %u"
args.append(str(line))
args.append(line)
LOG.log(LOG_LEVELS.get(level, logging.NOTSET), fmt, *args)


Expand Down
59 changes: 59 additions & 0 deletions tests/test_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# -*- coding: utf-8 eval: (blacken-mode 1) -*-
# SPDX-License-Identifier: MIT
#
# July 7 2025, Christian Hopps <[email protected]>
#
# Copyright (c) 2025, LabN Consulting, L.L.C.
#
import logging
import os
import sys
import unittest

from libyang import Context, LibyangError, configure_logging, temp_log_options


YANG_DIR = os.path.join(os.path.dirname(__file__), "yang")


class LogTest(unittest.TestCase):
def setUp(self):
self.ctx = Context(YANG_DIR)
configure_logging(False, logging.INFO)

def tearDown(self):
if self.ctx is not None:
self.ctx.destroy()
self.ctx = None

def _cause_log(self):
try:
assert self.ctx is not None
_ = self.ctx.parse_data_mem("bad", fmt="xml")
except LibyangError:
pass

@unittest.skipIf(sys.version_info < (3, 10), "Test requires Python 3.10+")
def test_configure_logging(self):
"""Test configure_logging API."""
with self.assertNoLogs("libyang", level="ERROR"):
self._cause_log()

configure_logging(True, logging.INFO)
with self.assertLogs("libyang", level="ERROR"):
self._cause_log()

@unittest.skipIf(sys.version_info < (3, 10), "Test requires Python 3.10+")
def test_with_temp_log(self):
"""Test configure_logging API."""
configure_logging(True, logging.INFO)

with self.assertLogs("libyang", level="ERROR"):
self._cause_log()

with self.assertNoLogs("libyang", level="ERROR"):
with temp_log_options(0):
self._cause_log()

with self.assertLogs("libyang", level="ERROR"):
self._cause_log()