-
Notifications
You must be signed in to change notification settings - Fork 272
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
Sync with latest upstream #527
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from geany import glog | ||
from traceback import format_exception | ||
import logging | ||
import sys | ||
|
||
|
||
GLIB_LOG_LEVEL_MAP = { | ||
logging.DEBUG: glog.LOG_LEVEL_DEBUG, | ||
logging.INFO: glog.LOG_LEVEL_INFO, | ||
logging.WARNING: glog.LOG_LEVEL_WARNING, | ||
# error and critical levels are swapped on purpose because | ||
# GLib interprets CRITICAL less fatal than Python and additionally | ||
# GLib abort()s the program on G_LOG_LEVEL_ERROR which is uncommon | ||
# in Python | ||
logging.ERROR: glog.LOG_LEVEL_CRITICAL, | ||
logging.CRITICAL: glog.LOG_LEVEL_ERROR, | ||
} | ||
|
||
|
||
class PluginLogger(object): | ||
""" | ||
Convenience wrapper softly emulating Python's logging interface. | ||
Any log messages are passed to the GLib log system using g_log() | ||
and the LOG_DOMAIN is set automatically to the plugin's name for convenience. | ||
""" | ||
|
||
def __init__(self, plugin_name): | ||
self._log_domain = u'geanypy-%s' % plugin_name | ||
|
||
def debug(self, msg_format, *args, **kwargs): | ||
self.log(logging.DEBUG, msg_format, *args, **kwargs) | ||
|
||
def info(self, msg_format, *args, **kwargs): | ||
self.log(logging.INFO, msg_format, *args, **kwargs) | ||
|
||
def message(self, msg_format, *args, **kwargs): | ||
self.log(glog.LOG_LEVEL_MESSAGE, msg_format, *args, **kwargs) | ||
|
||
def warning(self, msg_format, *args, **kwargs): | ||
self.log(logging.WARNING, msg_format, *args, **kwargs) | ||
|
||
def error(self, msg_format, *args, **kwargs): | ||
self.log(logging.ERROR, msg_format, *args, **kwargs) | ||
|
||
def exception(self, msg_format, *args, **kwargs): | ||
kwargs['exc_info'] = True | ||
self.error(msg_format, *args, **kwargs) | ||
|
||
def critical(self, msg_format, *args, **kwargs): | ||
self.log(logging.CRITICAL, msg_format, *args, **kwargs) | ||
|
||
warn = warning | ||
fatal = critical | ||
|
||
def log(self, level, msg_format, *args, **kwargs): | ||
# map log level from Python to GLib | ||
glib_log_level = GLIB_LOG_LEVEL_MAP.get(level, glog.LOG_LEVEL_MESSAGE) | ||
# format message | ||
log_message = msg_format % args | ||
# log exception information if requested | ||
exc_info = kwargs.get('exc_info', False) | ||
if exc_info: | ||
traceback_text = self._format_exception(exc_info) | ||
log_message = '%s\n%s' % (log_message, traceback_text) | ||
|
||
glog.glog(self._log_domain, glib_log_level, log_message) | ||
|
||
def _format_exception(self, exc_info): | ||
if not isinstance(exc_info, tuple): | ||
exc_info = sys.exc_info() | ||
exc_text_lines = format_exception(*exc_info) | ||
return ''.join(exc_text_lines) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ | |
|
||
#include "geanypy.h" | ||
|
||
|
||
typedef struct | ||
{ | ||
PyObject_HEAD | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,7 +62,7 @@ Editor_get_property(Editor *self, const gchar *prop_name) | |
PyObject *py_doc; | ||
py_doc = (PyObject *) Document_create_new_from_geany_document( | ||
self->editor->document); | ||
if (py_doc && py_doc != Py_None) | ||
if (!py_doc || py_doc == Py_None) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't look into this difference, I just picked the kind of condition that made the branch execute when it seemed plausible to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, the previous one seems weird: returning New condition seems more reasonable to me. I wonder if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's effectively like #define Py_RETURN_NONE do { Py_INCREF(Py_None); return Py_None; } while (0) or something similar. |
||
Py_RETURN_NONE; | ||
return py_doc; | ||
} | ||
|
@@ -296,7 +296,7 @@ static PyMethodDef Editor_methods[] = { | |
{ "indicator_set_on_range", (PyCFunction) Editor_indicator_set_on_range, METH_KEYWORDS, | ||
"Sets an indicator on the range specified." }, | ||
{ "insert_snippet", (PyCFunction) Editor_insert_snippet, METH_KEYWORDS, | ||
"Replces all special sequences in snippet and inserts it at " | ||
"Replaces all special sequences in snippet and inserts it at " | ||
"the specified position." }, | ||
{ "insert_text_block", (PyCFunction) Editor_insert_text_block, METH_KEYWORDS, | ||
"Inserts text, replacing tab chars and newline chars accordingly " | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#if defined(HAVE_CONFIG_H) && !defined(GEANYPY_WINDOWS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no license header? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not in each file. |
||
# include "config.h" | ||
#endif | ||
|
||
#include "geanypy.h" | ||
|
||
|
||
static PyObject * | ||
Glog_glog(PyObject *module, PyObject *args, PyObject *kwargs) | ||
{ | ||
static gchar *kwlist[] = { "log_domain", "log_level", "message", NULL }; | ||
gchar *log_domain, *message; | ||
GLogLevelFlags log_level; | ||
|
||
if (PyArg_ParseTupleAndKeywords(args, kwargs, "sis", kwlist, &log_domain, &log_level, &message)) | ||
{ | ||
g_log(log_domain, log_level, "%s", message); | ||
} | ||
Py_RETURN_NONE; | ||
} | ||
|
||
|
||
static | ||
PyMethodDef GlogModule_methods[] = { | ||
{ "glog", (PyCFunction) Glog_glog, METH_KEYWORDS, "Wrapper around g_log()." }, | ||
{ NULL } | ||
}; | ||
|
||
|
||
PyMODINIT_FUNC initglog(void) | ||
{ | ||
PyObject *m; | ||
|
||
m = Py_InitModule3("glog", GlogModule_methods, "GLib Log utility functions."); | ||
|
||
/* TODO: These constants are for the geany.logger.GLIB_LOG_LEVEL_MAP mapping. | ||
* It would be better to build this mapping on the C layer but how to | ||
* access the Python logging.* level constants here? */ | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_DEBUG", G_LOG_LEVEL_DEBUG); | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_INFO", G_LOG_LEVEL_INFO); | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_MESSAGE", G_LOG_LEVEL_MESSAGE); | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_WARNING", G_LOG_LEVEL_WARNING); | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_ERROR", G_LOG_LEVEL_ERROR); | ||
PyModule_AddIntConstant(m, "LOG_LEVEL_CRITICAL", G_LOG_LEVEL_CRITICAL); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the previous code is better. *_CFLAGS derived from PKG_CONFIG_CHECK() contain include paths (and usually nothing else) so they should be added to automake's *_CPPFLAGS indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really mind since they all end up jammed in the same part of the command line, but it seemed logical to group the pre-processor flags and the compiler flags into their respective variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*_CFLAGS derived from PKG_CONFIG_CHECK() contains mostly (usually exclusively) pre-processor flags, despite the name. And the order on the command line matters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess as long as user environment
CPPFLAGS
overrideCPPFLAGS
and likewise but after withCFLAGS
it doesn't matter.Edit: something like this
$(AM_CPPFLAGS) $(geanypy_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(geanypy_la_CFLAGS) $(CFLAGS)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this changes matters much, but IMO it's not bad, rather good. Yes, pkg-config will mostly fill the
*_CFLAGS
variable with preprocessor flags, but it might put other stuff here if it wants. Also, it's fine putting preprocessor flags in*_CFLAGS
AFAIK, only library order matters.