Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/cpp-python-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ jobs:
run: ctest --parallel $(sysctl -n hw.logicalcpu) --output-on-failure
- name: Build the source package for Python
run: |
python python/pyxstubgen.py --pyxfile=build/python/_jsbsim.pyx --output=python/_jsbsim.pyi
python python/pyxstubgen.py --pyxfile=build/python/_jsbsim.pyx --output=python/__init__.pyi
cp build/python/pyproject.toml .
python -m build --sdist
- name: Check reset for real time execution
Expand Down
2 changes: 1 addition & 1 deletion python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ target_link_libraries(_jsbsim PRIVATE libJSBSim)
set_target_properties(_jsbsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${JSBSIM_TEST_PACKAGE_DIR})
install(TARGETS _jsbsim DESTINATION jsbsim COMPONENT wheel)
install(FILES ${PROJECT_SOURCE_DIR}/python/__init__.py DESTINATION jsbsim COMPONENT wheel)
install(FILES ${PROJECT_SOURCE_DIR}/python/_jsbsim.pyi DESTINATION jsbsim COMPONENT wheel)
install(FILES ${PROJECT_SOURCE_DIR}/python/__init__.pyi DESTINATION jsbsim COMPONENT wheel)
install(PROGRAMS ${PROJECT_SOURCE_DIR}/python/JSBSim.py DESTINATION jsbsim
RENAME script.py COMPONENT wheel)

Expand Down
3 changes: 2 additions & 1 deletion python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from . import _jsbsim
from ._jsbsim import (
__version__,
Attribute,
BaseError,
DefaultLogger,
FGAerodynamics,
FGAircraft,
FGAtmosphere,
Expand All @@ -26,4 +26,5 @@
ePressure,
eTemperature,
get_default_root_dir,
set_logger,
)
8 changes: 4 additions & 4 deletions python/jsbsim.pyx.in
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@ LogLevel_PyClass = <PyObject*>LogLevel
LogFormat_PyClass = <PyObject*>LogFormat


def inherit_docstring(cls):
def _inherit_docstring_from_super_class(cls):
for name, func in cls.__dict__.items():
if not func.__doc__:
func.__doc__ = getattr(super(cls, cls), name).__doc__
return cls


@inherit_docstring
@_inherit_docstring_from_super_class
class DefaultLogger(FGLogger):
"""Default logger: print messages to stdout without formatting."""
def file_location(self, filename: str, line: int) -> None:
Expand Down Expand Up @@ -270,7 +270,7 @@ cdef class FGPropertyNode:
self.__intercept_invalid_pointer()
return GetFullyQualifiedName(self.thisptr.ptr()).decode()

def get_node(self, path: str, create: bool = False) -> Optional[SGPropertyNode]:
def get_node(self, path: str, create: bool = False) -> Optional[FGPropertyNode]:
"""Get a pointer to another node by relative path.

:param path: The relative path from the node.
Expand Down Expand Up @@ -325,7 +325,7 @@ cdef class FGPropertyManager:
if not self.thisptr:
raise MemoryError()

def get_node(self, path: Optional[str] = None, create: bool = False) -> Optional[SGPropertyNode]:
def get_node(self, path: Optional[str] = None, create: bool = False) -> Optional[FGPropertyNode]:
"""@Dox(JSBSim::FGPropertyManager::GetNode)"""
node = FGPropertyNode()
if path is None:
Expand Down
10 changes: 6 additions & 4 deletions python/pyxstubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# pyxstubgen.py
#
# Automatic generation of the JSBSim stub file `_jsbsim.pyi` from Cython's pyx file.
# Automatic generation of the JSBSim stub file `*.pyi` from Cython's pyx file.
#
# Copyright (c) 2025 Bertrand Coconnier
#
Expand Down Expand Up @@ -273,9 +273,9 @@ def python__string(self, tree: Tree) -> str:
def python__decorator(self, tree: Tree) -> str:
assert len(tree.children) == 2
assert tree.children[1] is None
self.output.write(
f"\n{self.TAB_SPACES*self.indent}@{dotted_name(tree.children[0])}"
)
decorator_name = dotted_name(tree.children[0])
if decorator_name[0] != "_":
self.output.write(f"\n{self.TAB_SPACES*self.indent}@{decorator_name}")

def funcdef(self, tree: Tree) -> None:
func_name: str = ""
Expand All @@ -293,6 +293,8 @@ def funcdef(self, tree: Tree) -> None:
func_name = rule_name(child)
if func_name in ("__cinit__", "__dealloc__"):
return
if func_name[0] == "_" and func_name[1] != '_':
return
elif child_type.value == "cparameters": # Get the function parameters
parameters: List[str] = []
for cparameter in child.children:
Expand Down
48 changes: 48 additions & 0 deletions src/input_output/FGLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,70 @@ CLASS DOCUMENTATION
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

/**
* Logging backend interface.
*
* JSBSim routes each log record to an `FGLogger` instance instead of writing
* directly to stdout/stderr. Applications can keep the default `FGLogConsole`
* backend, or provide their own subclass and register it through
* `SetLogger(FGLogger_ptr)`.
*
* A single log record follows this lifecycle:
* 1. `SetLevel()` starts a new log record and gives the severity.
* 2. `FileLocation()` may be called (typically for XML-related messages),
* immediately after `SetLevel()` and before message content.
* 3. `Message()` receives the textual payload. It can be invoked multiple times
* for one logical record because JSBSim may build a message in fragments.
* 4. `Format()` communicates formatting intent (colors, emphasis, reset) for
* the subsequent output. Implementations may ignore it if formatting is not
* applicable.
* 5. `Flush()` ends the current log record and is the right place to finalize
* and emit the record (for example: prefixing, buffering, forwarding to a
* UI, or forcing output synchronization).
*
* Implementations are expected to keep enough internal state between these
* callbacks to assemble one coherent log record.
*
* \see SetLogger
* \see GetLogger
*/
class JSBSIM_API FGLogger
{
public:
/// Virtual destructor for polymorphic use.
virtual ~FGLogger() {}
/// Starts a new log record and provides its severity level.
virtual void SetLevel(LogLevel level) { log_level = level;}
/// Optionally provides source filename and line for contextual diagnostics.
virtual void FileLocation(const std::string& filename, int line) {}
/// Appends message text. May be called multiple times per log record.
virtual void Message(const std::string& message) = 0;
/// Applies a formatting hint to subsequent output.
virtual void Format(LogFormat format) {}
/// Ends the current log record and commits any buffered output.
virtual void Flush(void) {}
protected:
LogLevel log_level = LogLevel::BULK;
};

using FGLogger_ptr = std::shared_ptr<FGLogger>;

/**
* Sets the active logger for the current thread.
*
* The logger is stored in thread-local storage: all JSBSim instances running
* in this thread share this same `FGLogger` instance, while other threads keep
* their own independent logger instance.
*
* \see GetLogger
*/
JSBSIM_API void SetLogger(FGLogger_ptr logger);

/**
* Returns the active logger for the current thread.
*
* \see SetLogger
*/
JSBSIM_API FGLogger_ptr GetLogger(void);

class JSBSIM_API FGLogging
Expand Down
Loading