FIrst pass at allow external plugins

This commit is contained in:
MinchinWeb 2020-12-13 21:28:19 -07:00
parent 1714d1eeef
commit e25869e9bc
18 changed files with 113 additions and 76 deletions

View file

@ -462,7 +462,7 @@ def run(context, command, text=""):
def load_template(context, filename): def load_template(context, filename):
full_path = os.path.join("features/data/templates", filename) full_path = os.path.join("features/data/templates", filename)
exporter = plugins.template_exporter.__exporter_from_file(full_path) exporter = plugins.template_exporter.__exporter_from_file(full_path)
plugins.__exporter_types[exporter.names[0]] = exporter plugins.meta.__exporter_types[exporter.names[0]] = exporter
@when('we set the keyring password of "{journal}" to "{password}"') @when('we set the keyring password of "{journal}" to "{password}"')

View file

@ -12,9 +12,9 @@ from .commands import postconfig_list
from .commands import preconfig_diagnostic from .commands import preconfig_diagnostic
from .commands import preconfig_version from .commands import preconfig_version
from .output import deprecated_cmd from .output import deprecated_cmd
from .plugins import EXPORT_FORMATS
from .plugins import IMPORT_FORMATS
from .plugins import util from .plugins import util
from .plugins.meta import EXPORT_FORMATS
from .plugins.meta import IMPORT_FORMATS
class WrappingFormatter(argparse.RawTextHelpFormatter): class WrappingFormatter(argparse.RawTextHelpFormatter):

View file

@ -47,7 +47,7 @@ def postconfig_list(config, **kwargs):
def postconfig_import(args, config, **kwargs): def postconfig_import(args, config, **kwargs):
from .Journal import open_journal from .Journal import open_journal
from .plugins import get_importer from .plugins.meta import get_importer
# Requires opening the journal # Requires opening the journal
journal = open_journal(args.journal_name, config) journal = open_journal(args.journal_name, config)

View file

View file

View file

@ -330,13 +330,13 @@ def _display_search_results(args, journal, **kwargs):
print(journal.pprint()) print(journal.pprint())
elif args.tags: elif args.tags:
print(plugins.get_exporter("tags").export(journal)) print(plugins.meta.get_exporter("tags").export(journal))
elif args.export: elif args.export:
exporter = plugins.get_exporter(args.export) exporter = plugins.meta.get_exporter(args.export)
print(exporter.export(journal, args.filename)) print(exporter.export(journal, args.filename))
elif kwargs["config"].get("display_format"): elif kwargs["config"].get("display_format"):
exporter = plugins.get_exporter(kwargs["config"]["display_format"]) exporter = plugins.meta.get_exporter(kwargs["config"]["display_format"])
print(exporter.export(journal, args.filename)) print(exporter.export(journal, args.filename))
else: else:
print(journal.pprint()) print(journal.pprint())

View file

@ -1,49 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
# Copyright (C) 2012-2021 jrnl contributors # Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html # License: https://www.gnu.org/licenses/gpl-3.0.html
from .fancy_exporter import FancyExporter
from .jrnl_importer import JRNLImporter
from .json_exporter import JSONExporter
from .markdown_exporter import MarkdownExporter
from .tag_exporter import TagExporter
from .dates_exporter import DatesExporter
from .template_exporter import __all__ as template_exporters
from .text_exporter import TextExporter
from .xml_exporter import XMLExporter
from .yaml_exporter import YAMLExporter
__exporters = [
JSONExporter,
MarkdownExporter,
TagExporter,
DatesExporter,
TextExporter,
XMLExporter,
YAMLExporter,
FancyExporter,
] + template_exporters
__importers = [JRNLImporter]
__exporter_types = {name: plugin for plugin in __exporters for name in plugin.names}
__exporter_types["pretty"] = None
__exporter_types["short"] = None
__importer_types = {name: plugin for plugin in __importers for name in plugin.names}
EXPORT_FORMATS = sorted(__exporter_types.keys())
IMPORT_FORMATS = sorted(__importer_types.keys())
def get_exporter(format):
for exporter in __exporters:
if hasattr(exporter, "names") and format in exporter.names:
return exporter
return None
def get_importer(format):
for importer in __importers:
if hasattr(importer, "names") and format in importer.names:
return importer
return None

View file

@ -5,10 +5,10 @@
from textwrap import TextWrapper from textwrap import TextWrapper
from .text_exporter import TextExporter from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
class FancyExporter(TextExporter): class Exporter(TextExporter):
"""This Exporter can convert entries and journals into text with unicode box drawing characters.""" """This Exporter can convert entries and journals into text with unicode box drawing characters."""
names = ["fancy", "boxed"] names = ["fancy", "boxed"]

View file

@ -5,11 +5,11 @@
import json import json
from .text_exporter import TextExporter from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
from .util import get_tags_count from jrnl.plugins.util import get_tags_count
class JSONExporter(TextExporter): class Exporter(TextExporter):
"""This Exporter can convert entries and journals into json.""" """This Exporter can convert entries and journals into json."""
names = ["json"] names = ["json"]

View file

@ -9,11 +9,10 @@ import sys
from jrnl.color import RESET_COLOR from jrnl.color import RESET_COLOR
from jrnl.color import WARNING_COLOR from jrnl.color import WARNING_COLOR
from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
from .text_exporter import TextExporter
class MarkdownExporter(TextExporter): class Exporter(TextExporter):
"""This Exporter can convert entries and journals into Markdown.""" """This Exporter can convert entries and journals into Markdown."""
names = ["md", "markdown"] names = ["md", "markdown"]

View file

@ -3,11 +3,11 @@
# Copyright (C) 2012-2021 jrnl contributors # Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html # License: https://www.gnu.org/licenses/gpl-3.0.html
from .text_exporter import TextExporter from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
from .util import get_tags_count from jrnl.plugins.util import get_tags_count
class TagExporter(TextExporter): class Exporter(TextExporter):
"""This Exporter can lists the tags for entries and journals, exported as a plain text file.""" """This Exporter can lists the tags for entries and journals, exported as a plain text file."""
names = ["tags"] names = ["tags"]

View file

@ -11,7 +11,7 @@ from jrnl.color import ERROR_COLOR
from jrnl.color import RESET_COLOR from jrnl.color import RESET_COLOR
class TextExporter: class Exporter:
"""This Exporter can convert entries and journals into text files.""" """This Exporter can convert entries and journals into text files."""
names = ["text", "txt"] names = ["text", "txt"]

View file

@ -5,11 +5,11 @@
from xml.dom import minidom from xml.dom import minidom
from .json_exporter import JSONExporter from jrnl.plugins.exporter.json_exporter import Exporter as JSONExporter
from .util import get_tags_count from jrnl.plugins.util import get_tags_count
class XMLExporter(JSONExporter): class Exporter(JSONExporter):
"""This Exporter can convert entries and journals into XML.""" """This Exporter can convert entries and journals into XML."""
names = ["xml"] names = ["xml"]

View file

@ -10,11 +10,10 @@ import sys
from jrnl.color import ERROR_COLOR from jrnl.color import ERROR_COLOR
from jrnl.color import RESET_COLOR from jrnl.color import RESET_COLOR
from jrnl.color import WARNING_COLOR from jrnl.color import WARNING_COLOR
from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
from .text_exporter import TextExporter
class YAMLExporter(TextExporter): class Exporter(TextExporter):
"""This Exporter can convert entries and journals into Markdown formatted text with YAML front matter.""" """This Exporter can convert entries and journals into Markdown formatted text with YAML front matter."""
names = ["yaml"] names = ["yaml"]

View file

@ -6,7 +6,7 @@
import sys import sys
class JRNLImporter: class Importer:
"""This plugin imports entries from other jrnl files.""" """This plugin imports entries from other jrnl files."""
names = ["jrnl"] names = ["jrnl"]

84
jrnl/plugins/meta.py Normal file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env python
# encoding: utf-8
import importlib
import pkgutil
import jrnl.contrib.exporter
import jrnl.contrib.importer
import jrnl.plugins.exporter
import jrnl.plugins.importer
from .template_exporter import __all__ as template_exporters
__exporters_builtin = list(
pkgutil.iter_modules(
jrnl.plugins.exporter.__path__, jrnl.plugins.exporter.__name__ + "."
)
)
__exporters_contrib = list(
pkgutil.iter_modules(
jrnl.contrib.exporter.__path__, jrnl.contrib.exporter.__name__ + "."
)
)
__importers_builtin = list(
pkgutil.iter_modules(
jrnl.plugins.importer.__path__, jrnl.plugins.importer.__name__ + "."
)
)
__importers_contrib = list(
pkgutil.iter_modules(
jrnl.contrib.importer.__path__, jrnl.contrib.importer.__name__ + "."
)
)
__exporter_types_builtin = {
name: importlib.import_module(plugin.name)
for plugin in __exporters_builtin
for name in importlib.import_module(plugin.name).Exporter.names
}
__exporter_types_contrib = {
name: importlib.import_module(plugin.name)
for plugin in __exporters_contrib
for name in importlib.import_module(plugin.name).Exporter.names
}
__exporter_types_template = {
name: plugin for plugin in template_exporters for name in plugin.names
}
__importer_types_builtin = {
name: importlib.import_module(plugin.name)
for plugin in __importers_builtin
for name in importlib.import_module(plugin.name).Importer.names
}
__importer_types_contrib = {
name: importlib.import_module(plugin.name)
for plugin in __importers_contrib
for name in importlib.import_module(plugin.name).Importer.names
}
__exporter_types = {
**__exporter_types_builtin,
**__exporter_types_contrib,
**__exporter_types_template,
}
__importer_types = {**__importer_types_builtin, **__importer_types_contrib}
EXPORT_FORMATS = sorted(__exporter_types.keys())
IMPORT_FORMATS = sorted(__importer_types.keys())
def get_exporter(format):
for exporter in __exporters:
if hasattr(exporter, "names") and format in exporter.names:
return exporter
return None
def get_importer(format):
for importer in __importers:
if hasattr(importer, "names") and format in importer.names:
return importer
return None

View file

@ -6,8 +6,8 @@
from glob import glob from glob import glob
import os import os
from .template import Template from jrnl.plugins.template import Template
from .text_exporter import TextExporter from jrnl.plugins.exporter.text_exporter import Exporter as TextExporter
class GenericTemplateExporter(TextExporter): class GenericTemplateExporter(TextExporter):
@ -31,7 +31,7 @@ def __exporter_from_file(template_file):
name = os.path.basename(template_file).replace(".template", "") name = os.path.basename(template_file).replace(".template", "")
template = Template.from_file(template_file) template = Template.from_file(template_file)
return type( return type(
str(f"{name.title()}Exporter"), str(f"{name.title()}TemplateExporter"),
(GenericTemplateExporter,), (GenericTemplateExporter,),
{"names": [name], "extension": template.extension, "template": template}, {"names": [name], "extension": template.extension, "template": template},
) )

View file

@ -3,11 +3,10 @@
# Copyright (C) 2012-2021 jrnl contributors # Copyright (C) 2012-2021 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html # License: https://www.gnu.org/licenses/gpl-3.0.html
def get_tags_count(journal): def get_tags_count(journal):
"""Returns a set of tuples (count, tag) for all tags present in the journal.""" """Returns a set of tuples (count, tag) for all tags present in the journal."""
# Astute reader: should the following line leave you as puzzled as me the first time # Astute reader: should the following line leave you as puzzled as me the first time
# I came across this construction, worry not and embrace the ensuing moment of enlightment. # I came across this construction, worry not and embrace the ensuing moment of enlightenment.
tags = [tag for entry in journal.entries for tag in set(entry.tags)] tags = [tag for entry in journal.entries for tag in set(entry.tags)]
# To be read: [for entry in journal.entries: for tag in set(entry.tags): tag] # To be read: [for entry in journal.entries: for tag in set(entry.tags): tag]
tag_counts = {(tags.count(tag), tag) for tag in tags} tag_counts = {(tags.count(tag), tag) for tag in tags}