From 9015fa646e04fc3cb180bea24c33d34edbb48ed7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 9 Feb 2013 15:37:35 -0500 Subject: python: build html docs using sphinx Build instructions: make make DESTIDIR=/tmp/... install make DESTIDIR=/tmp/... sphinx-html sphinx-man sphinx-epub ... --- src/python-systemd/docs/conf.py | 288 ++++++++++++++++++++++++++++++++++++ src/python-systemd/docs/id128.rst | 7 + src/python-systemd/docs/index.rst | 22 +++ src/python-systemd/docs/journal.rst | 11 ++ 4 files changed, 328 insertions(+) create mode 100644 src/python-systemd/docs/conf.py create mode 100644 src/python-systemd/docs/id128.rst create mode 100644 src/python-systemd/docs/index.rst create mode 100644 src/python-systemd/docs/journal.rst (limited to 'src/python-systemd/docs') diff --git a/src/python-systemd/docs/conf.py b/src/python-systemd/docs/conf.py new file mode 100644 index 0000000000..4a55778b7d --- /dev/null +++ b/src/python-systemd/docs/conf.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# +# python-systemd documentation build configuration file, created by +# sphinx-quickstart on Sat Feb 9 13:49:42 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'python-systemd' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '197' +# The full version, including alpha/beta/rc tags. +release = '197' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-systemddoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'python-systemd.tex', u'python-systemd Documentation', + None, 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'python-systemd', u'python-systemd Documentation', + [], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'python-systemd', u'python-systemd Documentation', + u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks', 'python-systemd', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'python-systemd' +epub_author = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks' +epub_publisher = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks' +epub_copyright = u'2013, David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/src/python-systemd/docs/id128.rst b/src/python-systemd/docs/id128.rst new file mode 100644 index 0000000000..e817d803a7 --- /dev/null +++ b/src/python-systemd/docs/id128.rst @@ -0,0 +1,7 @@ +`systemd.id128` module +====================== + +.. automodule:: systemd.id128 + :members: + :undoc-members: + :inherited-members: diff --git a/src/python-systemd/docs/index.rst b/src/python-systemd/docs/index.rst new file mode 100644 index 0000000000..f04d5a181c --- /dev/null +++ b/src/python-systemd/docs/index.rst @@ -0,0 +1,22 @@ +.. python-systemd documentation master file, created by + sphinx-quickstart on Sat Feb 9 13:49:42 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to python-systemd's documentation! +========================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + journal + id128 + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst new file mode 100644 index 0000000000..036250a764 --- /dev/null +++ b/src/python-systemd/docs/journal.rst @@ -0,0 +1,11 @@ +`systemd.journal` module +======================== + +.. automodule:: systemd.journal + :members: send, sendv, stream, stream_fd + :undoc-members: + +`JournalHandler` class +---------------------- + +.. autoclass:: JournalHandler -- cgit v1.2.3-54-g00ecf From c1db45c6a5b0bd2ad7ddbfd877162794ac3a48f8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 16 Feb 2013 20:28:34 -0500 Subject: sphinx: document Journal class too --- src/python-systemd/docs/journal.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/python-systemd/docs') diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst index 036250a764..89728a2ecb 100644 --- a/src/python-systemd/docs/journal.rst +++ b/src/python-systemd/docs/journal.rst @@ -9,3 +9,16 @@ ---------------------- .. autoclass:: JournalHandler + +Accessing the Journal +--------------------- + +.. autoclass:: _Journal + :undoc-members: + :inherited-members: + +.. autoclass:: Journal + :undoc-members: + :inherited-members: + + .. automethod:: __init__ -- cgit v1.2.3-54-g00ecf From df2795d9f94ec1e17a5b780261b21ac8d9f22101 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 21 Feb 2013 15:07:39 +0100 Subject: systemd-python: document attributes In id128 it would be better to add everything automatically, but sphinx cannot do this right now. --- src/python-systemd/docs/id128.rst | 31 +++++++++++++++++++++++++++++++ src/python-systemd/docs/journal.rst | 23 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'src/python-systemd/docs') diff --git a/src/python-systemd/docs/id128.rst b/src/python-systemd/docs/id128.rst index e817d803a7..12c28f362b 100644 --- a/src/python-systemd/docs/id128.rst +++ b/src/python-systemd/docs/id128.rst @@ -5,3 +5,34 @@ :members: :undoc-members: :inherited-members: + + .. autoattribute:: systemd.id128.SD_MESSAGE_COREDUMP + .. autoattribute:: systemd.id128.SD_MESSAGE_FORWARD_SYSLOG_MISSED + .. autoattribute:: systemd.id128.SD_MESSAGE_HIBERNATE_KEY + .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_DROPPED + .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_MISSED + .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_START + .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_STOP + .. autoattribute:: systemd.id128.SD_MESSAGE_LID_CLOSED + .. autoattribute:: systemd.id128.SD_MESSAGE_LID_OPENED + .. autoattribute:: systemd.id128.SD_MESSAGE_OVERMOUNTING + .. autoattribute:: systemd.id128.SD_MESSAGE_POWER_KEY + .. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_START + .. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_STOP + .. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_START + .. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_STOP + .. autoattribute:: systemd.id128.SD_MESSAGE_SHUTDOWN + .. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_START + .. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_STOP + .. autoattribute:: systemd.id128.SD_MESSAGE_SPAWN_FAILED + .. autoattribute:: systemd.id128.SD_MESSAGE_STARTUP_FINISHED + .. autoattribute:: systemd.id128.SD_MESSAGE_SUSPEND_KEY + .. autoattribute:: systemd.id128.SD_MESSAGE_TIMEZONE_CHANGE + .. autoattribute:: systemd.id128.SD_MESSAGE_TIME_CHANGE + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_FAILED + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADED + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADING + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTED + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTING + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPED + .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPING diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst index 89728a2ecb..9d627ce3ed 100644 --- a/src/python-systemd/docs/journal.rst +++ b/src/python-systemd/docs/journal.rst @@ -22,3 +22,26 @@ Accessing the Journal :inherited-members: .. automethod:: __init__ + +.. autoattribute:: systemd.journal.DEFAULT_CONVERTERS + +Whence constants +~~~~~~~~~~~~~~~~ + +.. autoattribute:: systemd.journal.SEEK_SET +.. autoattribute:: systemd.journal.SEEK_CUR +.. autoattribute:: systemd.journal.SEEK_END + +Journal access types +~~~~~~~~~~~~~~~~~~~~ + +.. autoattribute:: systemd.journal.LOCAL_ONLY +.. autoattribute:: systemd.journal.RUNTIME_ONLY +.. autoattribute:: systemd.journal.SYSTEM_ONLY + +Journal event types +~~~~~~~~~~~~~~~~~~~ + +.. autoattribute:: systemd.journal.NOP +.. autoattribute:: systemd.journal.APPEND +.. autoattribute:: systemd.journal.INVALIDATE -- cgit v1.2.3-54-g00ecf From 86e3d32a1d52cd2ccba184e8375da8828914d3ff Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 23 Feb 2013 01:11:36 +0100 Subject: systemd-python: return both parts of sd_journal_get_monotonic_usec In Python 3, a named tuple is used. In Python 2, a simple tuple is used. In either case, the pair is (timestamp, bootid). --- src/python-systemd/_reader.c | 74 +++++++++++++++++++++++++++++++------ src/python-systemd/docs/journal.rst | 2 + src/python-systemd/journal.py | 8 +++- 3 files changed, 71 insertions(+), 13 deletions(-) (limited to 'src/python-systemd/docs') diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c index 9262c89e4d..7645cb9a84 100644 --- a/src/python-systemd/_reader.c +++ b/src/python-systemd/_reader.c @@ -67,6 +67,26 @@ static int set_error(int r, const char* path, const char* invalid_message) { return 1; } +#if PY_MAJOR_VERSION >= 3 +static PyTypeObject MonotonicType; + +PyDoc_STRVAR(MonotonicType__doc__, + "A tuple of (timestamp, bootid) for holding monotonic timestamps"); + +static PyStructSequence_Field MonotonicType_fields[] = { + {(char*) "timestamp", (char*) "Time"}, + {(char*) "bootid", (char*) "Unique identifier of the boot"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc Monotonic_desc = { + (char*) "journal.Monotonic", + MonotonicType__doc__, + MonotonicType_fields, + 2, +}; +#endif + static void Journal_dealloc(Journal* self) { sd_journal_close(self->j); @@ -221,22 +241,37 @@ static PyObject* Journal_get_next(Journal *self, PyObject *args) } { - PyObject _cleanup_Py_DECREF_ *key = NULL, *value = NULL; - sd_id128_t sd_id; + PyObject _cleanup_Py_DECREF_ + *key = NULL, *timestamp = NULL, *bytes = NULL, *value = NULL; + sd_id128_t id; uint64_t monotonic; - r = sd_journal_get_monotonic_usec(self->j, &monotonic, &sd_id); + r = sd_journal_get_monotonic_usec(self->j, &monotonic, &id); if (set_error(r, NULL, NULL)) goto error; + assert_cc(sizeof(unsigned long long) == sizeof(monotonic)); key = unicode_FromString("__MONOTONIC_TIMESTAMP"); - if (!key) + timestamp = PyLong_FromUnsignedLongLong(monotonic); + bytes = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes)); +#if PY_MAJOR_VERSION >= 3 + value = PyStructSequence_New(&MonotonicType); +#else + value = PyTuple_New(2); +#endif + if (!key || !timestamp || !bytes || !value) goto error; - assert_cc(sizeof(unsigned long long) == sizeof(monotonic)); - value = PyLong_FromUnsignedLongLong(monotonic); - if (!value) - goto error; + Py_INCREF(timestamp); + Py_INCREF(bytes); + +#if PY_MAJOR_VERSION >= 3 + PyStructSequence_SET_ITEM(value, 0, timestamp); + PyStructSequence_SET_ITEM(value, 1, bytes); +#else + PyTuple_SET_ITEM(value, 0, timestamp); + PyTuple_SET_ITEM(value, 1, bytes); +#endif if (PyDict_SetItem(dict, key, value)) goto error; @@ -421,7 +456,7 @@ static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args) double timedouble; char *bootid = NULL; uint64_t timestamp; - sd_id128_t sd_id; + sd_id128_t id; int r; if (!PyArg_ParseTuple(args, "d|z", &timedouble, &bootid)) @@ -435,19 +470,19 @@ static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args) } if (bootid) { - r = sd_id128_from_string(bootid, &sd_id); + r = sd_id128_from_string(bootid, &id); if (set_error(r, NULL, "Invalid bootid")) return NULL; } else { Py_BEGIN_ALLOW_THREADS - r = sd_id128_get_boot(&sd_id); + r = sd_id128_get_boot(&id); Py_END_ALLOW_THREADS if (set_error(r, NULL, NULL)) return NULL; } Py_BEGIN_ALLOW_THREADS - r = sd_journal_seek_monotonic_usec(self->j, sd_id, timestamp); + r = sd_journal_seek_monotonic_usec(self->j, id, timestamp); Py_END_ALLOW_THREADS if (set_error(r, NULL, NULL)) return NULL; @@ -671,6 +706,10 @@ static PyModuleDef _reader_module = { }; #endif +#if PY_MAJOR_VERSION >= 3 +static bool initialized = false; +#endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-prototypes" @@ -696,6 +735,11 @@ init_reader(void) m = PyModule_Create(&_reader_module); if (m == NULL) return NULL; + + if (!initialized) { + PyStructSequence_InitType(&MonotonicType, &Monotonic_desc); + initialized = true; + } #else m = Py_InitModule3("_reader", NULL, SUMMARY); if (m == NULL) @@ -703,7 +747,13 @@ init_reader(void) #endif Py_INCREF(&JournalType); +#if PY_MAJOR_VERSION >= 3 + Py_INCREF(&MonotonicType); +#endif if (PyModule_AddObject(m, "_Journal", (PyObject *) &JournalType) || +#if PY_MAJOR_VERSION >= 3 + PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) || +#endif PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) || PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) || PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) || diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst index 9d627ce3ed..38ab57e45b 100644 --- a/src/python-systemd/docs/journal.rst +++ b/src/python-systemd/docs/journal.rst @@ -23,6 +23,8 @@ Accessing the Journal .. automethod:: __init__ +.. autoclass:: Monotonic + .. autoattribute:: systemd.journal.DEFAULT_CONVERTERS Whence constants diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py index d94934cfa8..a5641e98b2 100644 --- a/src/python-systemd/journal.py +++ b/src/python-systemd/journal.py @@ -38,7 +38,13 @@ from ._reader import (_Journal, NOP, APPEND, INVALIDATE, LOCAL_ONLY, RUNTIME_ONLY, SYSTEM_ONLY) from . import id128 as _id128 -_MONOTONIC_CONVERTER = lambda x: _datetime.timedelta(microseconds=x) +if _sys.version_info >= (3,): + from ._reader import Monotonic +else: + Monotonic = tuple + +_MONOTONIC_CONVERTER = lambda p: Monotonic((_datetime.timedelta(microseconds=p[0]), + _uuid.UUID(bytes=p[1]))) _REALTIME_CONVERTER = lambda x: _datetime.datetime.fromtimestamp(x / 1E6) DEFAULT_CONVERTERS = { 'MESSAGE_ID': _uuid.UUID, -- cgit v1.2.3-54-g00ecf From 7f41820b07ccb8a6da5552c466818fcce3d085bf Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 28 Feb 2013 19:32:31 -0500 Subject: python-systemd: rename Journal to Reader It seems inevitable that we'll also grow a writing interface, and then it'll be cumbersome to have a "Journal" for reading, and a "Writer" for writing. --- src/python-systemd/_reader.c | 122 ++++++++++++++++++------------------ src/python-systemd/docs/journal.rst | 4 +- src/python-systemd/journal.py | 28 ++++----- 3 files changed, 77 insertions(+), 77 deletions(-) (limited to 'src/python-systemd/docs') diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c index 7645cb9a84..7f200d53f6 100644 --- a/src/python-systemd/_reader.c +++ b/src/python-systemd/_reader.c @@ -50,8 +50,8 @@ typedef struct { PyObject_HEAD sd_journal *j; -} Journal; -static PyTypeObject JournalType; +} Reader; +static PyTypeObject ReaderType; static int set_error(int r, const char* path, const char* invalid_message) { if (r >= 0) @@ -87,15 +87,15 @@ static PyStructSequence_Desc Monotonic_desc = { }; #endif -static void Journal_dealloc(Journal* self) +static void Reader_dealloc(Reader* self) { sd_journal_close(self->j); Py_TYPE(self)->tp_free((PyObject*)self); } -PyDoc_STRVAR(Journal__doc__, - "Journal([flags][,path]) -> ...\n\n" - "Journal allows filtering and retrieval of Journal entries.\n" +PyDoc_STRVAR(Reader__doc__, + "Reader([flags][,path]) -> ...\n\n" + "Reader allows filtering and retrieval of Journal entries.\n" "Argument `flags` sets open flags of the journal, which can be one\n" "of, or ORed combination of constants: LOCAL_ONLY (default) opens\n" "journal on local machine only; RUNTIME_ONLY opens only\n" @@ -104,7 +104,7 @@ PyDoc_STRVAR(Journal__doc__, "Argument `path` is the directory of journal files. Note that\n" "currently flags are ignored when `path` is present as they are\n" "not relevant."); -static int Journal_init(Journal *self, PyObject *args, PyObject *keywds) +static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) { int flags = SD_JOURNAL_LOCAL_ONLY, r; char *path = NULL; @@ -124,11 +124,11 @@ static int Journal_init(Journal *self, PyObject *args, PyObject *keywds) return set_error(r, path, "Invalid flags or path"); } -PyDoc_STRVAR(Journal_get_next__doc__, +PyDoc_STRVAR(Reader_get_next__doc__, "get_next([skip]) -> dict\n\n" "Return dictionary of the next log entry. Optional skip value will\n" "return the `skip`\\-th log entry."); -static PyObject* Journal_get_next(Journal *self, PyObject *args) +static PyObject* Reader_get_next(Reader *self, PyObject *args) { PyObject *dict; const void *msg; @@ -303,11 +303,11 @@ error: return NULL; } -PyDoc_STRVAR(Journal_get_previous__doc__, +PyDoc_STRVAR(Reader_get_previous__doc__, "get_previous([skip]) -> dict\n\n" "Return dictionary of the previous log entry. Optional skip value\n" "will return the -`skip`\\-th log entry. Equivalent to get_next(-skip)."); -static PyObject* Journal_get_previous(Journal *self, PyObject *args) +static PyObject* Reader_get_previous(Reader *self, PyObject *args) { int64_t skip = 1LL; if (!PyArg_ParseTuple(args, "|L", &skip)) @@ -317,13 +317,13 @@ static PyObject* Journal_get_previous(Journal *self, PyObject *args) (char*) "L", -skip); } -PyDoc_STRVAR(Journal_add_match__doc__, +PyDoc_STRVAR(Reader_add_match__doc__, "add_match(match) -> None\n\n" "Add a match to filter journal log entries. All matches of different\n" "fields are combined with logical AND, and matches of the same field\n" "are automatically combined with logical OR.\n" "Match is a string of the form \"FIELD=value\"."); -static PyObject* Journal_add_match(Journal *self, PyObject *args, PyObject *keywds) +static PyObject* Reader_add_match(Reader *self, PyObject *args, PyObject *keywds) { char *match; int match_len, r; @@ -338,10 +338,10 @@ static PyObject* Journal_add_match(Journal *self, PyObject *args, PyObject *keyw Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_add_disjunction__doc__, +PyDoc_STRVAR(Reader_add_disjunction__doc__, "add_disjunction() -> None\n\n" "Inserts a logical OR between matches added before and afterwards."); -static PyObject* Journal_add_disjunction(Journal *self, PyObject *args) +static PyObject* Reader_add_disjunction(Reader *self, PyObject *args) { int r; r = sd_journal_add_disjunction(self->j); @@ -351,23 +351,23 @@ static PyObject* Journal_add_disjunction(Journal *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_flush_matches__doc__, +PyDoc_STRVAR(Reader_flush_matches__doc__, "flush_matches() -> None\n\n" "Clear all current match filters."); -static PyObject* Journal_flush_matches(Journal *self, PyObject *args) +static PyObject* Reader_flush_matches(Reader *self, PyObject *args) { sd_journal_flush_matches(self->j); Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_seek__doc__, +PyDoc_STRVAR(Reader_seek__doc__, "seek(offset[, whence]) -> None\n\n" "Jump `offset` entries in the journal. Argument\n" "`whence` defines what the offset is relative to:\n" "os.SEEK_SET (default) from first match in journal;\n" "os.SEEK_CUR from current position in journal;\n" "and os.SEEK_END is from last match in journal."); -static PyObject* Journal_seek(Journal *self, PyObject *args, PyObject *keywds) +static PyObject* Reader_seek(Reader *self, PyObject *args, PyObject *keywds) { int64_t offset; int whence = SEEK_SET; @@ -418,11 +418,11 @@ static PyObject* Journal_seek(Journal *self, PyObject *args, PyObject *keywds) Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_seek_realtime__doc__, +PyDoc_STRVAR(Reader_seek_realtime__doc__, "seek_realtime(realtime) -> None\n\n" "Seek to nearest matching journal entry to `realtime`. Argument\n" "`realtime` can must be an integer unix timestamp."); -static PyObject* Journal_seek_realtime(Journal *self, PyObject *args) +static PyObject* Reader_seek_realtime(Reader *self, PyObject *args) { double timedouble; uint64_t timestamp; @@ -445,13 +445,13 @@ static PyObject* Journal_seek_realtime(Journal *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_seek_monotonic__doc__, +PyDoc_STRVAR(Reader_seek_monotonic__doc__, "seek_monotonic(monotonic[, bootid]) -> None\n\n" "Seek to nearest matching journal entry to `monotonic`. Argument\n" "`monotonic` is an timestamp from boot in seconds.\n" "Argument `bootid` is a string representing which boot the\n" "monotonic time is reference to. Defaults to current bootid."); -static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args) +static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args) { double timedouble; char *bootid = NULL; @@ -489,7 +489,7 @@ static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(Journal_wait__doc__, +PyDoc_STRVAR(Reader_wait__doc__, "wait([timeout]) -> state change (integer)\n\n" "Wait for a change in the journal. Argument `timeout` specifies\n" "the maximum number of seconds to wait before returning\n" @@ -498,7 +498,7 @@ PyDoc_STRVAR(Journal_wait__doc__, "Will return constants: NOP if no change; APPEND if new\n" "entries have been added to the end of the journal; and\n" "INVALIDATE if journal files have been added or removed."); -static PyObject* Journal_wait(Journal *self, PyObject *args, PyObject *keywds) +static PyObject* Reader_wait(Reader *self, PyObject *args, PyObject *keywds) { int r; int64_t timeout = 0LL; @@ -515,10 +515,10 @@ static PyObject* Journal_wait(Journal *self, PyObject *args, PyObject *keywds) return long_FromLong(r); } -PyDoc_STRVAR(Journal_seek_cursor__doc__, +PyDoc_STRVAR(Reader_seek_cursor__doc__, "seek_cursor(cursor) -> None\n\n" "Seek to journal entry by given unique reference `cursor`."); -static PyObject* Journal_seek_cursor(Journal *self, PyObject *args) +static PyObject* Reader_seek_cursor(Reader *self, PyObject *args) { const char *cursor; int r; @@ -534,13 +534,13 @@ static PyObject* Journal_seek_cursor(Journal *self, PyObject *args) Py_RETURN_NONE; } -static PyObject* Journal_iter(PyObject *self) +static PyObject* Reader_iter(PyObject *self) { Py_INCREF(self); return self; } -static PyObject* Journal_iternext(PyObject *self) +static PyObject* Reader_iternext(PyObject *self) { PyObject *dict; Py_ssize_t dict_size; @@ -558,11 +558,11 @@ static PyObject* Journal_iternext(PyObject *self) } } -PyDoc_STRVAR(Journal_query_unique__doc__, +PyDoc_STRVAR(Reader_query_unique__doc__, "query_unique(field) -> a set of values\n\n" "Return a set of unique values appearing in journal for the\n" "given `field`. Note this does not respect any journal matches."); -static PyObject* Journal_query_unique(Journal *self, PyObject *args) +static PyObject* Reader_query_unique(Reader *self, PyObject *args) { char *query; int r; @@ -601,7 +601,7 @@ PyDoc_STRVAR(data_threshold__doc__, "Fields longer than this will be truncated to the threshold size.\n" "Defaults to 64Kb."); -static PyObject* Journal_get_data_threshold(Journal *self, void *closure) +static PyObject* Reader_get_data_threshold(Reader *self, void *closure) { size_t cvalue; int r; @@ -613,7 +613,7 @@ static PyObject* Journal_get_data_threshold(Journal *self, void *closure) return long_FromSize_t(cvalue); } -static int Journal_set_data_threshold(Journal *self, PyObject *value, void *closure) +static int Reader_set_data_threshold(Reader *self, PyObject *value, void *closure) { int r; if (value == NULL) { @@ -628,36 +628,36 @@ static int Journal_set_data_threshold(Journal *self, PyObject *value, void *clos return set_error(r, NULL, NULL); } -static PyGetSetDef Journal_getseters[] = { +static PyGetSetDef Reader_getseters[] = { {(char*) "data_threshold", - (getter) Journal_get_data_threshold, - (setter) Journal_set_data_threshold, + (getter) Reader_get_data_threshold, + (setter) Reader_set_data_threshold, (char*) data_threshold__doc__, NULL}, {NULL} }; -static PyMethodDef Journal_methods[] = { - {"get_next", (PyCFunction) Journal_get_next, METH_VARARGS, Journal_get_next__doc__}, - {"get_previous", (PyCFunction) Journal_get_previous, METH_VARARGS, Journal_get_previous__doc__}, - {"add_match", (PyCFunction) Journal_add_match, METH_VARARGS|METH_KEYWORDS, Journal_add_match__doc__}, - {"add_disjunction", (PyCFunction) Journal_add_disjunction, METH_NOARGS, Journal_add_disjunction__doc__}, - {"flush_matches", (PyCFunction) Journal_flush_matches, METH_NOARGS, Journal_flush_matches__doc__}, - {"seek", (PyCFunction) Journal_seek, METH_VARARGS | METH_KEYWORDS, Journal_seek__doc__}, - {"seek_realtime", (PyCFunction) Journal_seek_realtime, METH_VARARGS, Journal_seek_realtime__doc__}, - {"seek_monotonic", (PyCFunction) Journal_seek_monotonic, METH_VARARGS, Journal_seek_monotonic__doc__}, - {"wait", (PyCFunction) Journal_wait, METH_VARARGS, Journal_wait__doc__}, - {"seek_cursor", (PyCFunction) Journal_seek_cursor, METH_VARARGS, Journal_seek_cursor__doc__}, - {"query_unique", (PyCFunction) Journal_query_unique, METH_VARARGS, Journal_query_unique__doc__}, +static PyMethodDef Reader_methods[] = { + {"get_next", (PyCFunction) Reader_get_next, METH_VARARGS, Reader_get_next__doc__}, + {"get_previous", (PyCFunction) Reader_get_previous, METH_VARARGS, Reader_get_previous__doc__}, + {"add_match", (PyCFunction) Reader_add_match, METH_VARARGS|METH_KEYWORDS, Reader_add_match__doc__}, + {"add_disjunction", (PyCFunction) Reader_add_disjunction, METH_NOARGS, Reader_add_disjunction__doc__}, + {"flush_matches", (PyCFunction) Reader_flush_matches, METH_NOARGS, Reader_flush_matches__doc__}, + {"seek", (PyCFunction) Reader_seek, METH_VARARGS | METH_KEYWORDS, Reader_seek__doc__}, + {"seek_realtime", (PyCFunction) Reader_seek_realtime, METH_VARARGS, Reader_seek_realtime__doc__}, + {"seek_monotonic", (PyCFunction) Reader_seek_monotonic, METH_VARARGS, Reader_seek_monotonic__doc__}, + {"wait", (PyCFunction) Reader_wait, METH_VARARGS, Reader_wait__doc__}, + {"seek_cursor", (PyCFunction) Reader_seek_cursor, METH_VARARGS, Reader_seek_cursor__doc__}, + {"query_unique", (PyCFunction) Reader_query_unique, METH_VARARGS, Reader_query_unique__doc__}, {NULL} /* Sentinel */ }; -static PyTypeObject JournalType = { +static PyTypeObject ReaderType = { PyVarObject_HEAD_INIT(NULL, 0) - "_reader._Journal", /*tp_name*/ - sizeof(Journal), /*tp_basicsize*/ + "_reader._Reader", /*tp_name*/ + sizeof(Reader), /*tp_basicsize*/ 0, /*tp_itemsize*/ - (destructor)Journal_dealloc, /*tp_dealloc*/ + (destructor)Reader_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -673,22 +673,22 @@ static PyTypeObject JournalType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - Journal__doc__, /* tp_doc */ + Reader__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - Journal_iter, /* tp_iter */ - Journal_iternext, /* tp_iternext */ - Journal_methods, /* tp_methods */ + Reader_iter, /* tp_iter */ + Reader_iternext, /* tp_iternext */ + Reader_methods, /* tp_methods */ 0, /* tp_members */ - Journal_getseters, /* tp_getset */ + Reader_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc) Journal_init, /* tp_init */ + (initproc) Reader_init, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; @@ -724,7 +724,7 @@ init_reader(void) PyDateTime_IMPORT; - if (PyType_Ready(&JournalType) < 0) + if (PyType_Ready(&ReaderType) < 0) #if PY_MAJOR_VERSION >= 3 return NULL; #else @@ -746,11 +746,11 @@ init_reader(void) return; #endif - Py_INCREF(&JournalType); + Py_INCREF(&ReaderType); #if PY_MAJOR_VERSION >= 3 Py_INCREF(&MonotonicType); #endif - if (PyModule_AddObject(m, "_Journal", (PyObject *) &JournalType) || + if (PyModule_AddObject(m, "_Reader", (PyObject *) &ReaderType) || #if PY_MAJOR_VERSION >= 3 PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) || #endif diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst index 38ab57e45b..78b831afff 100644 --- a/src/python-systemd/docs/journal.rst +++ b/src/python-systemd/docs/journal.rst @@ -13,11 +13,11 @@ Accessing the Journal --------------------- -.. autoclass:: _Journal +.. autoclass:: _Reader :undoc-members: :inherited-members: -.. autoclass:: Journal +.. autoclass:: Reader :undoc-members: :inherited-members: diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py index a5641e98b2..23e1d65747 100644 --- a/src/python-systemd/journal.py +++ b/src/python-systemd/journal.py @@ -34,7 +34,7 @@ if _sys.version_info >= (3,): from syslog import (LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG) from ._journal import sendv, stream_fd -from ._reader import (_Journal, NOP, APPEND, INVALIDATE, +from ._reader import (_Reader, NOP, APPEND, INVALIDATE, LOCAL_ONLY, RUNTIME_ONLY, SYSTEM_ONLY) from . import id128 as _id128 @@ -86,15 +86,15 @@ if _sys.version_info >= (3,): else: _convert_unicode = _functools.partial(unicode, encoding='utf-8') -class Journal(_Journal): - """Journal allows the access and filtering of systemd journal +class Reader(_Reader): + """Reader allows the access and filtering of systemd journal entries. Note that in order to access the system journal, a non-root user must be in the `adm` group. Example usage to print out all error or higher level messages for systemd-udevd for the boot: - >>> myjournal = journal.Journal() + >>> myjournal = journal.Reader() >>> myjournal.add_boot_match(journal.CURRENT_BOOT) >>> myjournal.add_loglevel_matches(journal.LOG_ERR) >>> myjournal.add_match(_SYSTEMD_UNIT="systemd-udevd.service") @@ -105,7 +105,7 @@ class Journal(_Journal): found in the journal. """ def __init__(self, converters=None, flags=LOCAL_ONLY, path=None): - """Creates instance of Journal, which allows filtering and + """Create an instance of Reader, which allows filtering and return of journal entries. Argument `converters` is a dictionary which updates the DEFAULT_CONVERTERS to convert journal field values. @@ -118,7 +118,7 @@ class Journal(_Journal): currently flags are ignored when `path` is present as they are currently not relevant. """ - super(Journal, self).__init__(flags, path) + super(Reader, self).__init__(flags, path) if _sys.version_info >= (3,3): self.converters = _ChainMap() if converters is not None: @@ -164,7 +164,7 @@ class Journal(_Journal): args = list(args) args.extend(_make_line(key, val) for key, val in kwargs.items()) for arg in args: - super(Journal, self).add_match(arg) + super(Reader, self).add_match(arg) def get_next(self, skip=1): """Return the next log entry as a dictionary of fields. @@ -172,21 +172,21 @@ class Journal(_Journal): Optional skip value will return the `skip`\-th log entry. Entries will be processed with converters specified during - Journal creation. + Reader creation. """ return self._convert_entry( - super(Journal, self).get_next(skip)) + super(Reader, self).get_next(skip)) def query_unique(self, field): - """Return unique values appearing in the Journal for given `field`. + """Return unique values appearing in the journal for given `field`. Note this does not respect any journal matches. Entries will be processed with converters specified during - Journal creation. + Reader creation. """ return set(self._convert_field(field, value) - for value in super(Journal, self).query_unique(field)) + for value in super(Reader, self).query_unique(field)) def seek_realtime(self, realtime): """Seek to a matching journal entry nearest to `realtime` time. @@ -196,7 +196,7 @@ class Journal(_Journal): """ if isinstance(realtime, _datetime.datetime): realtime = float(realtime.strftime("%s.%f")) - return super(Journal, self).seek_realtime(realtime) + return super(Reader, self).seek_realtime(realtime) def seek_monotonic(self, monotonic, bootid=None): """Seek to a matching journal entry nearest to `monotonic` time. @@ -210,7 +210,7 @@ class Journal(_Journal): monotonic = monotonic.totalseconds() if isinstance(bootid, _uuid.UUID): bootid = bootid.get_hex() - return super(Journal, self).seek_monotonic(monotonic, bootid) + return super(Reader, self).seek_monotonic(monotonic, bootid) def log_level(self, level): """Set maximum log `level` by setting matches for PRIORITY. -- cgit v1.2.3-54-g00ecf