improved code documentation

This commit is contained in:
MinchinWeb 2021-05-09 13:49:35 -06:00
parent 2a70636b4d
commit f22d985330
3 changed files with 68 additions and 10 deletions

View file

@ -3,14 +3,33 @@
# Extending jrnl
jrnl can be extended with custom importers and exporters.
*jrnl* can be extended with custom importers and exporters.
Note that custom importers and exporters can be given the same name as a
built-in importer or exporter to override it.
Custom Importers and Exporters are traditional Python packages, and are
installed (into jrnl) simply by installing them so they are available to the
Python interpreter that is running jrnl.
installed (into *jrnl*) simply by installing them so they are available to the
Python interpreter that is running *jrnl*.
Exporter are also used as "formatters" when entries are written to the command
line.
## Rational
I added this feature because *jrnl* was overall working well for me, but I
found myself maintaining a private fork so I could have a slightly customized
export format. Implemeneting (import and) export plugins was seen as a way to
maintain my custom exporter without the need to maintaining my private fork.
This implementation tries to keep plugins as light as possible, and as free of
boilerplate code as reasonable. As well, internal importers and exporters are
implemented in almost exactly the same way as custom importers and exporters,
and so it is hoped that plugins can be moved from "contributed" to "internal"
easily, or that internal plugins can serve as a base and/or a demonstration for
external plugins.
-- @MinchinWeb, May 2021
## Entry Class
@ -63,7 +82,9 @@ Some implementation notes:
- The importer class must be named **Importer**, and should sub-class
**jrnl.plugins.base.BaseImporter**.
- The importer module must be within the **jrnl.contrib.importer** namespace.
- The importer must not have any `__init__.py` files in the base directories.
- The importer must not have any `__init__.py` files in the base directories
(but you can have one for your importer base directory if it is in a
directory rather than a single file).
- The importer must be installed as a Python package available to the same
Python interpreter running jrnl.
- The importer must expose at least the following the following members:
@ -85,7 +106,7 @@ generator or blogging engine.
An exporter take either a whole journal or a specific entry and exports it.
Below is a basic JSON Exporter; note that a more extensive JSON exporter is
included in jrnl and so this (if installed) would override the built in
included in *jrnl* and so this (if installed) would override the built in
exporter.
~~~ python
@ -103,7 +124,9 @@ Some implementation notes:
- the exporter class must be named **Exporter** and should sub-class
**jrnl.plugins.base.BaseExporter**.
- the exporter module must be within the **jrnl.contrib.exporter** namespace.
- The exporter must not have any `__init__.py` files in the base directories.
- The exporter must not have any `__init__.py` files in the base directories
(but you can have one for your exporter base directory if it is in a
directory rather than a single file).
- The exporter must be installed as a Python package available to the same
Python interpreter running jrnl.
- the exporter should expose at least the following the following members
@ -118,11 +141,16 @@ Some implementation notes:
- **extension** (string): the file extention used on exported entries.
- **export_entry(entry)**: given an entry, returns a string of the formatted,
exported entry.
- **export_journal(journal)**: given a journal, returns a string of the
formatted, exported entries of the journal.
- **export_journal(journal)**: (optional) given a journal, returns a string
of the formatted, exported entries of the journal. If not implemented,
*jrnl* will call **export_entry()** on each entry in turn and then
concatenate the results together.
## Development Tips
- editable installs (`pip install -e ...`) don't seem to play nice with
the namespace layout. If your plugin isn't appearing, try a non-editable
install of both jrnl and your plugin.
install of both *jrnl* and your plugin.
- for examples, you can look to the *jrnl*'s internal importers and exporters.
As well, there are some basic external examples included in *jrnl*'s git repo
at `tests/external_plugins_src` (including the example code above).

View file

@ -1,5 +1,20 @@
#!/usr/bin/env python
# encoding: utf-8
# Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html
"""
This file ("meta") uses that title in the reflexive sense; i.e. it is the
collection of code that allows plugins to deal with themselves.
In particular, the code here collects the list of imports and exporters, both
internal and external, and tells the main program which plugins are available.
Actual calling of the plugins is done directly and works because given plugin
functions are importable/callable at predetermined (code) locations.
Internal plugins are located in the `jrnl.plugins` namespace, and external
plugins are located in the `jrnl.contrib` namespace.
"""
import importlib
import pkgutil
@ -64,10 +79,15 @@ __importer_types = {
}
EXPORT_FORMATS = sorted(__exporter_types.keys())
"""list of stings: all available export formats."""
IMPORT_FORMATS = sorted(__importer_types.keys())
"""list of stings: all available import formats."""
def get_exporter(format):
"""
Given an export format, returns the (callable) class of the corresponding exporter.
"""
# print('get_exporter')
# print(__exporter_types)
for exporter_name, exporter_class in __exporter_types.items():
@ -82,6 +102,9 @@ def get_exporter(format):
def get_importer(format):
"""
Given an import format, returns the (callable) class of the corresponding importer.
"""
for importer_name, importer_class in __importer_types.items():
if (
hasattr(importer_class, "Importer")

View file

@ -4,7 +4,14 @@
# License: https://www.gnu.org/licenses/gpl-3.0.html
"""
Exporter for testing and experimentation purposes
Exporter for testing and experimentation purposes.
The presence of this plugin is also used as a "switch" by the test suite to
decide on whether or not to run the "vanilla" test suite, or the test suite
for external plugins.
The `export_entry` and `export_journal` methods are both purposely not
implemented to confirm behavior on plugins that don't implement them.
"""
from jrnl.plugins.base import BaseExporter