Skip to content

Commit 18449d9

Browse files
committed
Initial public version of SciJava logging for Jython
0 parents  commit 18449d9

File tree

11 files changed

+1119
-0
lines changed

11 files changed

+1119
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# VS Code workspace files
2+
*.code-workspace
3+
4+
# maven / release generated files
5+
target/
6+
pom.xml.releaseBackup
7+
8+
# bytecode created when importing directly in Jython:
9+
*py.class

DESC.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:snake::coffee::bookmark_tabs: Jython package for using SciJava's LogService for logging.

LICENSE.txt

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# SciJava log handler for Python :snake::coffee::bookmark_tabs:
2+
3+
A very thin Python package (mavenized for [ImageJ2][imagej]) to use the
4+
[SciJava][gh_scijava] [LogService][gh_sj_logservice] as a handler for
5+
[Python's logging facility][py_logging]. See the wiki page about
6+
[Logging][ij_logging] for more details about ImageJ's logging framework.
7+
8+
Developed and provided by the [Imaging Core Facility (IMCF)][imcf] of the
9+
Biozentrum, University of Basel, Switzerland.
10+
11+
# Example usage
12+
13+
The snippet below demonstrates how to use the handler in an ImageJ2 Python
14+
script utilizing the fabulous [Script Parameters][ij_script_params] for
15+
retrieving the LogService instance.
16+
17+
```Python
18+
#@ LogService sjlogservice
19+
20+
from sjlogging.logger import setup_scijava_logger
21+
from sjlogging.setter import set_loglevel
22+
23+
24+
def log_messages(level):
25+
log.critical("+++ new round of messages (level %s) +++" % level)
26+
set_loglevel(level)
27+
log.debug('debug log message')
28+
log.info('info log message')
29+
log.warn('warn log message')
30+
log.error('error log message')
31+
log.critical('critical log message')
32+
log.critical("--- finished round of messages (level %s) ---" % level)
33+
34+
35+
log = setup_scijava_logger(sjlogservice)
36+
37+
log_messages('WARNING')
38+
log_messages('INFO')
39+
log_messages('DEBUG')
40+
log_messages('WARNING')
41+
```
42+
43+
44+
[imcf]: https://www.biozentrum.unibas.ch/imcf
45+
[imagej]: https://imagej.net
46+
[ij_logging]: https://imagej.net/Logging
47+
[ij_script_params]: http://imagej.net/Script_Parameters
48+
[py_logging]: https://docs.python.org/2/library/logging.html
49+
[gh_scijava]: https://github.com/scijava
50+
[gh_sj_logservice]: https://github.com/scijava/scijava-common/tree/master/src/main/java/org/scijava/log

pom.xml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>org.scijava</groupId>
7+
<artifactId>pom-scijava</artifactId>
8+
<version>23.2.0</version>
9+
<relativePath />
10+
</parent>
11+
12+
<groupId>ch.unibas.biozentrum.imcf</groupId>
13+
<artifactId>jython-scijava-logging</artifactId>
14+
<version>0.4.4-SNAPSHOT</version>
15+
16+
<name>Jython-SciJava Logging</name>
17+
<description>
18+
Jython package for using SciJava's LogService for logging.
19+
</description>
20+
<url>https://github.com/imcf/jython-scijava-logging/</url>
21+
<inceptionYear>2013</inceptionYear>
22+
<organization>
23+
<name>University of Basel</name>
24+
<url>http://www.unibas.ch/</url>
25+
</organization>
26+
<licenses>
27+
<license>
28+
<name>GNU General Public License (GPL) v3+</name>
29+
<url>https://www.gnu.org/licenses/gpl.html</url>
30+
<distribution>repo</distribution>
31+
</license>
32+
</licenses>
33+
34+
<build>
35+
<!-- The following filtering rule allows to automatically have the
36+
project version added to the Python package's `__init__.py` file by
37+
placing the string '${project.version}' somewhere in that file. -->
38+
<resources>
39+
<resource>
40+
<directory>src/main/resources</directory>
41+
<filtering>true</filtering>
42+
<includes>
43+
<include>**/__init__.py</include>
44+
</includes>
45+
</resource>
46+
<resource>
47+
<directory>src/main/resources</directory>
48+
<filtering>false</filtering>
49+
<excludes>
50+
<exclude>**/__init__.py</exclude>
51+
</excludes>
52+
</resource>
53+
</resources>
54+
</build>
55+
56+
<developers>
57+
<!-- See https://imagej.net/Team -->
58+
<developer>
59+
<id>Ehrenfeu</id>
60+
<name>Niko Ehrenfeuchter</name>
61+
<url>https://imagej.net/User:Ehrenfeu</url>
62+
<roles>
63+
<role>founder</role>
64+
<role>lead</role>
65+
<role>developer</role>
66+
<role>debugger</role>
67+
<role>reviewer</role>
68+
<role>support</role>
69+
<role>maintainer</role>
70+
</roles>
71+
</developer>
72+
</developers>
73+
<contributors>
74+
<!--
75+
NB: Need at least one element to override the parent.
76+
See: https://issues.apache.org/jira/browse/MNG-5220
77+
-->
78+
<contributor>
79+
<name>None</name>
80+
</contributor>
81+
</contributors>
82+
83+
<mailingLists>
84+
<mailingList>
85+
<name>Image.sc Forum</name>
86+
<archive>https://forum.image.sc/</archive>
87+
</mailingList>
88+
</mailingLists>
89+
90+
<scm>
91+
<connection>scm:git:git://github.com/imcf/jython-scijava-logging</connection>
92+
<developerConnection>scm:git:[email protected]:imcf/jython-scijava-logging</developerConnection>
93+
<tag>HEAD</tag>
94+
<url>https://github.com/imcf/jython-scijava-logging</url>
95+
</scm>
96+
<issueManagement>
97+
<system>GitHub Issues</system>
98+
<url>https://github.com/imcf/jython-scijava-logging/issues</url>
99+
</issueManagement>
100+
<ciManagement>
101+
<system>None</system>
102+
</ciManagement>
103+
104+
<properties>
105+
<license.licenseName>gpl_v3</license.licenseName>
106+
<license.copyrightOwners>University of Basel, Switzerland</license.copyrightOwners>
107+
<maven.source.skip>true</maven.source.skip>
108+
</properties>
109+
110+
<repositories>
111+
<repository>
112+
<id>imagej.public</id>
113+
<url>http://maven.imagej.net/content/groups/public</url>
114+
</repository>
115+
</repositories>
116+
117+
<dependencies>
118+
<dependency>
119+
<groupId>net.imagej</groupId>
120+
<artifactId>ij</artifactId>
121+
<scope>provided</scope>
122+
</dependency>
123+
</dependencies>
124+
</project>

scripts/build_and_deploy.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
### exit on any error
4+
set -e
5+
6+
cd $(dirname $0)/..
7+
8+
9+
10+
FIJI_APP="/opt/Fiji.app"
11+
if [ -n "$1" ] ; then
12+
FIJI_APP="$1"
13+
fi
14+
15+
16+
### build and deploy
17+
mvn -Dimagej.app.directory="$FIJI_APP"

scripts/example.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#@ LogService sjlogservice
2+
3+
from sjlogging.logger import setup_scijava_logger
4+
from sjlogging.setter import set_loglevel
5+
6+
7+
def log_messages(level):
8+
log.critical("+++ new round of messages (level %s) +++" % level)
9+
set_loglevel(level)
10+
log.debug('debug log message')
11+
log.info('info log message')
12+
log.warn('warn log message')
13+
log.error('error log message')
14+
log.critical('critical log message')
15+
log.critical("--- finished round of messages (level %s) ---" % level)
16+
17+
18+
log = setup_scijava_logger(sjlogservice)
19+
20+
log_messages('WARNING')
21+
log_messages('INFO')
22+
log_messages('DEBUG')
23+
log_messages('WARNING')
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""SciJava log handler for Python
2+
3+
A very thin Python package (mavenized for [ImageJ2][imagej]) to use the
4+
[SciJava][gh_scijava] [LogService][gh_sj_logservice] as a handler for
5+
[Python's logging facility][py_logging]. See the wiki page about
6+
[Logging][ij_logging] for more details about ImageJ's logging framework.
7+
8+
Developed and provided by the [Imaging Core Facility (IMCF)][imcf] of the
9+
Biozentrum, University of Basel, Switzerland.
10+
11+
# Example usage
12+
13+
The snippet below demonstrate how to use the handler in an ImageJ2 Python script
14+
utilizing the fabulous [Script Parameters][ij_script_params].
15+
16+
```Python
17+
#@ LogService sjlogservice
18+
19+
from sjlogging.logger import setup_scijava_logger
20+
from sjlogging.setter import set_loglevel
21+
22+
23+
def log_messages(level):
24+
log.critical("+++ new round of messages (level %s) +++" % level)
25+
set_loglevel(level)
26+
log.debug('debug log message')
27+
log.info('info log message')
28+
log.warn('warn log message')
29+
log.error('error log message')
30+
log.critical('critical log message')
31+
log.critical("--- finished round of messages (level %s) ---" % level)
32+
33+
34+
log = setup_scijava_logger(sjlogservice)
35+
36+
log_messages('WARNING')
37+
log_messages('INFO')
38+
log_messages('DEBUG')
39+
log_messages('WARNING')
40+
```
41+
42+
43+
[imcf]: https://www.biozentrum.unibas.ch/imcf
44+
[imagej]: https://imagej.net
45+
[ij_logging]: https://imagej.net/Logging
46+
[py_logging]: https://docs.python.org/2/library/logging.html
47+
[gh_scijava]: https://github.com/scijava
48+
[gh_sj_logservice]: https://github.com/scijava/scijava-common/tree/master/src/main/java/org/scijava/log
49+
"""
50+
51+
__version__ = '${project.version}'
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""Logging handler class redirecting messages to SciJava's LogService."""
2+
3+
import logging
4+
5+
6+
class SciJavaLogHandler(logging.StreamHandler):
7+
8+
"""A logging handler for routing messages to the SciJava LogService.
9+
10+
This class provides an easy way to create a Handler object for Python's
11+
'logging' package that will re-route messages to the [SciJava][1]
12+
LogService.
13+
14+
[1]: https://github.com/scijava/scijava-common/
15+
"""
16+
17+
def __init__(self, sjlog):
18+
"""Initialize the logging handler for the SciJava logging.
19+
20+
Parameters
21+
----------
22+
sjlog : org.scijava.log.LogService
23+
The LogService instance, usually retrieved in a script by using the
24+
SciJava script parameters annotation '#@ LogService logs' or
25+
equivalent.
26+
"""
27+
super(SciJavaLogHandler, self).__init__()
28+
self.sjlog = sjlog
29+
30+
def emit(self, record):
31+
"""Call the corresponding SciJava logging method.
32+
33+
Before the log message is handed over to the SciJava LogService we make
34+
sure the log-level of that very service is set accordingly.
35+
36+
Rationale:
37+
38+
All the level-handling for a given message has already been done by the
39+
Python logging filters etc., so once the emit() method is called we *do*
40+
know this message should actually be put out. Hence we first remember
41+
the current SciJava log level, adjust it according to the level of the
42+
given record, then we call the corresponding LogService method and
43+
finally we re-set the SciJava log level to the value it had when this
44+
method was called.
45+
"""
46+
# remember the current LogService level:
47+
sjlevel = self.sjlog.getLevel()
48+
49+
if record.levelname == "DEBUG":
50+
self.sjlog.setLevel(4)
51+
self.sjlog.debug(self.format(record))
52+
elif record.levelname == "INFO":
53+
self.sjlog.setLevel(3)
54+
self.sjlog.info(self.format(record))
55+
elif record.levelname == "WARNING":
56+
self.sjlog.setLevel(2)
57+
self.sjlog.warn(self.format(record))
58+
else: # everything else, including "ERROR" and "CRITICAL":
59+
self.sjlog.setLevel(1)
60+
self.sjlog.error(self.format(record))
61+
62+
# reset the LogService level to its previous value:
63+
self.sjlog.setLevel(sjlevel)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Base module for setting up a logger using the SciJava LogService."""
2+
3+
import logging
4+
5+
from .handler import SciJavaLogHandler
6+
7+
# This will get the root-logger, thus all settings will affect all child loggers
8+
# unless they are explicitly configured different. We could consider to (maybe
9+
# optionally) return a package-specific logger by using getLogger(__name__),
10+
# allowing the calling code to adjust its very own log level only.
11+
LOG = logging.getLogger()
12+
13+
def setup_scijava_logger(sjlogservice):
14+
"""Wrapper to add the SciJava handler to the logger.
15+
16+
Parameters
17+
----------
18+
sjlogservice : org.scijava.log.LogService
19+
The LogService instance, usually retrieved in a SciJava script by using
20+
the script parameters annotation '#@ LogService logs' or equivalent.
21+
22+
Returns
23+
-------
24+
log : logging.Logger
25+
The Python logger object.
26+
"""
27+
LOG.addHandler(SciJavaLogHandler(sjlogservice))
28+
return LOG

0 commit comments

Comments
 (0)