From 5920a0860d2291fb7d6962a47d5e16d8efdb6a3f Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Thu, 24 May 2018 21:57:42 +0200 Subject: [PATCH] Added a tag loader class. --- test/test_html.py | 1 + .../{tags/builtin => builtin_tags}/Align.py | 2 +- .../{tags/builtin => builtin_tags}/Code.py | 2 +- .../{tags/builtin => builtin_tags}/Image.py | 2 +- .../{tags/builtin => builtin_tags}/Label.py | 2 +- .../{tags/builtin => builtin_tags}/Link.py | 2 +- .../builtin => builtin_tags}/Progress.py | 2 +- .../{tags/builtin => builtin_tags}/Quote.py | 4 +- .../{tags/builtin => builtin_tags}/Rot.py | 2 +- .../{tags/builtin => builtin_tags}/Show.py | 2 +- .../{tags/builtin => builtin_tags}/Spoiler.py | 4 +- .../{tags/builtin => builtin_tags}/Text.py | 4 +- .../{tags/builtin => builtin_tags}/Title.py | 2 +- .../{tags/builtin => builtin_tags}/Video.py | 2 +- .../builtin => builtin_tags}/__init__.py | 0 textoutpc/{tags/base.py => tags.py} | 86 +++++++++++++++++-- textoutpc/tags/__init__.py | 73 ---------------- textoutpc/translate.py | 18 ++-- 18 files changed, 108 insertions(+), 102 deletions(-) rename textoutpc/{tags/builtin => builtin_tags}/Align.py (95%) rename textoutpc/{tags/builtin => builtin_tags}/Code.py (96%) rename textoutpc/{tags/builtin => builtin_tags}/Image.py (98%) rename textoutpc/{tags/builtin => builtin_tags}/Label.py (96%) rename textoutpc/{tags/builtin => builtin_tags}/Link.py (97%) rename textoutpc/{tags/builtin => builtin_tags}/Progress.py (95%) rename textoutpc/{tags/builtin => builtin_tags}/Quote.py (91%) rename textoutpc/{tags/builtin => builtin_tags}/Rot.py (94%) rename textoutpc/{tags/builtin => builtin_tags}/Show.py (93%) rename textoutpc/{tags/builtin => builtin_tags}/Spoiler.py (93%) rename textoutpc/{tags/builtin => builtin_tags}/Text.py (98%) rename textoutpc/{tags/builtin => builtin_tags}/Title.py (94%) rename textoutpc/{tags/builtin => builtin_tags}/Video.py (98%) rename textoutpc/{tags/builtin => builtin_tags}/__init__.py (100%) rename textoutpc/{tags/base.py => tags.py} (60%) mode change 100755 => 100644 delete mode 100755 textoutpc/tags/__init__.py diff --git a/test/test_html.py b/test/test_html.py index 439d10a..2fbfed2 100755 --- a/test/test_html.py +++ b/test/test_html.py @@ -40,6 +40,7 @@ __test_cases = { '[left]': '', '[left]lol[/]hi': '

lol

hi

', 'a[justify]b': '

a

b

', + 'a[i]': '

a

', 'a[i][justify]b': '

a

' \ '

b

', 'a[i]k[center]b': '

ak

' \ diff --git a/textoutpc/tags/builtin/Align.py b/textoutpc/builtin_tags/Align.py similarity index 95% rename from textoutpc/tags/builtin/Align.py rename to textoutpc/builtin_tags/Align.py index abcbe9e..b28e03b 100755 --- a/textoutpc/tags/builtin/Align.py +++ b/textoutpc/builtin_tags/Align.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag __all__ = ["TextoutAlignTag"] diff --git a/textoutpc/tags/builtin/Code.py b/textoutpc/builtin_tags/Code.py similarity index 96% rename from textoutpc/tags/builtin/Code.py rename to textoutpc/builtin_tags/Code.py index fd60431..83dc24b 100755 --- a/textoutpc/tags/builtin/Code.py +++ b/textoutpc/builtin_tags/Code.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag, \ +from ..tags import TextoutBlockTag as _TextoutBlockTag, \ TextoutInlineTag as _TextoutInlineTag __all__ = ["TextoutCodeTag", "TextoutInlineCodeTag", "TextoutNoEvalTag"] diff --git a/textoutpc/tags/builtin/Image.py b/textoutpc/builtin_tags/Image.py similarity index 98% rename from textoutpc/tags/builtin/Image.py rename to textoutpc/builtin_tags/Image.py index ff9d676..b24ee1e 100755 --- a/textoutpc/tags/builtin/Image.py +++ b/textoutpc/builtin_tags/Image.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag from html import escape as _htmlescape __all__ = ["TextoutImageTag", "TextoutAdminImageTag"] diff --git a/textoutpc/tags/builtin/Label.py b/textoutpc/builtin_tags/Label.py similarity index 96% rename from textoutpc/tags/builtin/Label.py rename to textoutpc/builtin_tags/Label.py index 7df8db6..8845488 100755 --- a/textoutpc/tags/builtin/Label.py +++ b/textoutpc/builtin_tags/Label.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutInlineTag as _TextoutInlineTag +from ..tags import TextoutInlineTag as _TextoutInlineTag import re as _re __all__ = ["TextoutLabelTag", "TextoutTargetTag"] diff --git a/textoutpc/tags/builtin/Link.py b/textoutpc/builtin_tags/Link.py similarity index 97% rename from textoutpc/tags/builtin/Link.py rename to textoutpc/builtin_tags/Link.py index 914aac7..50a77ed 100755 --- a/textoutpc/tags/builtin/Link.py +++ b/textoutpc/builtin_tags/Link.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutInlineTag as _TextoutInlineTag +from ..tags import TextoutInlineTag as _TextoutInlineTag from html import escape as _htmlescape __all__ = ["TextoutLinkTag", "TextoutProfileTag"] diff --git a/textoutpc/tags/builtin/Progress.py b/textoutpc/builtin_tags/Progress.py similarity index 95% rename from textoutpc/tags/builtin/Progress.py rename to textoutpc/builtin_tags/Progress.py index 4f3119c..f99d96a 100755 --- a/textoutpc/tags/builtin/Progress.py +++ b/textoutpc/builtin_tags/Progress.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag __all__ = ["TextoutProgressTag"] diff --git a/textoutpc/tags/builtin/Quote.py b/textoutpc/builtin_tags/Quote.py similarity index 91% rename from textoutpc/tags/builtin/Quote.py rename to textoutpc/builtin_tags/Quote.py index 2a729f9..5cbf7b8 100755 --- a/textoutpc/tags/builtin/Quote.py +++ b/textoutpc/builtin_tags/Quote.py @@ -4,9 +4,9 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag from html import escape as _htmlescape -from ...smileys import htmlsmileys as _htmlsmileys +from ..smileys import htmlsmileys as _htmlsmileys __all__ = ["TextoutQuoteTag"] diff --git a/textoutpc/tags/builtin/Rot.py b/textoutpc/builtin_tags/Rot.py similarity index 94% rename from textoutpc/tags/builtin/Rot.py rename to textoutpc/builtin_tags/Rot.py index a89386d..7c2090b 100755 --- a/textoutpc/tags/builtin/Rot.py +++ b/textoutpc/builtin_tags/Rot.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutInlineTag as _TextoutInlineTag +from ..tags import TextoutInlineTag as _TextoutInlineTag import string as _string __all__ = ["TextoutRotTag"] diff --git a/textoutpc/tags/builtin/Show.py b/textoutpc/builtin_tags/Show.py similarity index 93% rename from textoutpc/tags/builtin/Show.py rename to textoutpc/builtin_tags/Show.py index 617436a..9abc13c 100755 --- a/textoutpc/tags/builtin/Show.py +++ b/textoutpc/builtin_tags/Show.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag from html import escape as _htmlescape __all__ = ["TextoutShowTag"] diff --git a/textoutpc/tags/builtin/Spoiler.py b/textoutpc/builtin_tags/Spoiler.py similarity index 93% rename from textoutpc/tags/builtin/Spoiler.py rename to textoutpc/builtin_tags/Spoiler.py index 36aeb43..755a276 100755 --- a/textoutpc/tags/builtin/Spoiler.py +++ b/textoutpc/builtin_tags/Spoiler.py @@ -4,9 +4,9 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag from html import escape as _htmlescape -from ...smileys import htmlsmileys as _htmlsmileys +from ..smileys import htmlsmileys as _htmlsmileys __all__ = ["TextoutSpoilerTag"] diff --git a/textoutpc/tags/builtin/Text.py b/textoutpc/builtin_tags/Text.py similarity index 98% rename from textoutpc/tags/builtin/Text.py rename to textoutpc/builtin_tags/Text.py index bcf54fd..0c69844 100755 --- a/textoutpc/tags/builtin/Text.py +++ b/textoutpc/builtin_tags/Text.py @@ -4,8 +4,8 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutInlineTag as _TextoutInlineTag -from ...color import get_color +from ..tags import TextoutInlineTag as _TextoutInlineTag +from ..color import get_color __all__ = ["TextoutTextTag"] diff --git a/textoutpc/tags/builtin/Title.py b/textoutpc/builtin_tags/Title.py similarity index 94% rename from textoutpc/tags/builtin/Title.py rename to textoutpc/builtin_tags/Title.py index 2d2ffa7..01b0e44 100755 --- a/textoutpc/tags/builtin/Title.py +++ b/textoutpc/builtin_tags/Title.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag __all__ = ["TextoutTitleTag"] diff --git a/textoutpc/tags/builtin/Video.py b/textoutpc/builtin_tags/Video.py similarity index 98% rename from textoutpc/tags/builtin/Video.py rename to textoutpc/builtin_tags/Video.py index 5df06ae..eb1ea10 100755 --- a/textoutpc/tags/builtin/Video.py +++ b/textoutpc/builtin_tags/Video.py @@ -4,7 +4,7 @@ # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -from ..base import TextoutBlockTag as _TextoutBlockTag +from ..tags import TextoutBlockTag as _TextoutBlockTag import re as _re import urllib.parse as _urlparse from html import escape as _htmlescape diff --git a/textoutpc/tags/builtin/__init__.py b/textoutpc/builtin_tags/__init__.py similarity index 100% rename from textoutpc/tags/builtin/__init__.py rename to textoutpc/builtin_tags/__init__.py diff --git a/textoutpc/tags/base.py b/textoutpc/tags.py old mode 100755 new mode 100644 similarity index 60% rename from textoutpc/tags/base.py rename to textoutpc/tags.py index 8cab7f3..51439e8 --- a/textoutpc/tags/base.py +++ b/textoutpc/tags.py @@ -3,22 +3,28 @@ # Copyright (C) 2018 Thomas "Cakeisalie5" Touhey # This file is part of the textoutpc project, which is MIT-licensed. #****************************************************************************** -""" Base class for textout tags. For your class to be used as a textout tag, - you have to make it inherit one of these (usually `TextoutBlockTag` - or `TextoutInlineTag`). """ +""" Base classes to use with tags in textoutpc, with a manager class. + + For your tag to be used as a textoutpc tag, you have to make it + inherit one of the `TextoutBlockTag` or `TextoutInlineTag` classes. + + Making separate tag modules is possible through the manager class, + which allows not to hardcode the tags into the module. """ -import inspect as _inspect from functools import partial as _p -from inspect import getargspec as _getargspec +from inspect import ismodule as _ismod, isclass as _isclass, \ + getargspec as _getargspec, getfullargspec as _getfullargspec, \ + currentframe as _currentframe, getouterframes as _getouterframes +from importlib import import_module as _importmod -__all__ = ["TextoutTag", "TextoutBlockTag", "TextoutInlineTag", +__all__ = ["TextoutTags", "TextoutTag", "TextoutBlockTag", "TextoutInlineTag", "TextoutParagraphTag"] def _getargscount(func): try: - return len(_inspect.getfullargspec(func).args) + return len(_getfullargspec(func).args) except: - return len(_inspect.getargspec(func).args) + return len(_getargspec(func).args) # --- # Main base tag class. @@ -147,4 +153,68 @@ class TextoutParagraphTag(TextoutBlockTag): def end_html(self): return '

' +# --- +# Tag extractor. +# --- + +class TextoutTags: + """ Tag manager. + Object responsible for getting the tags. """ + + def __init__(self, *modules): + self._aliases = {} + for mod in modules: + self.import_tags(mod) + + def __extract_tags(self, module): + """ Extract tags from a module. """ + + tags = [] + + # Obtain the list of properties from the module. + + try: + ds = module.__all__ + except: + ds = dir(module) + + # Get the submodules from the module (usually different files in the + # tags module folder). + + for submodule in (obj for name, obj in ((nm, getattr(module, nm)) \ + for nm in ds) if (name == '__init__' or name[0] != '_') \ + and _ismod(obj)): + obtained = self.__extract_tags(submodule) + tags += [tag for tag in obtained \ + if not any(tag is x for x in tags)] + del obtained + + # Extract the tags from the current module. + + for tag in (obj for name, obj in ((nm, getattr(module, nm)) \ + for nm in ds) if name[0] != '_' and _isclass(obj) \ + and issubclass(obj, TextoutTag)): + tags.append(tag) + + return tags + + def import_tags(self, module): + """ Import tags from a dedicated module. """ + + if not _ismod(module): + module = _importmod(module, + _getouterframes(_currentframe(), 1)[0].name) + for tag in self.__extract_tags(module): + for alias in tag.aliases: + self._aliases[alias] = tag + + def get_tag(self, name, value, output_type = 'html', tweaks = {}): + """ Initialize a tag. """ + + try: + als = self._aliases[name] + return als(name, value, output_type, tweaks) + except: + return None + # End of file. diff --git a/textoutpc/tags/__init__.py b/textoutpc/tags/__init__.py deleted file mode 100755 index e723721..0000000 --- a/textoutpc/tags/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -#****************************************************************************** -# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey -# This file is part of the textoutpc project, which is MIT-licensed. -#****************************************************************************** -""" Tag helpers for the translate utilities. - As we ought to be able to make separate tag modules, this module - does not hardcode the imports and makes it possible to import any - custom module to isolate some tags from the others and make the - `textoutpc` a generic module for BBcode. -""" - -from inspect import ismodule as _ismod, isclass as _isclass -from .base import TextoutTag as _TextoutTag, TextoutBlockTag, \ - TextoutInlineTag, TextoutParagraphTag - -__all__ = ["TextoutParagraphTag", "TextoutBlockTag", "TextoutInlineTag", - "get_tag"] - -# --- -# Gathering of the tags. -# --- - -def _extract_tags(module): - """ Load all tags from a module. """ - - tags = [] - - # Obtain the list of properties from the module. - - try: - ds = module.__all__ - except: - ds = dir(module) - - # Get the submodules from the module (usually different files in the - # tags module folder). - - for submodule in (obj for name, obj in ((nm, getattr(module, nm)) \ - for nm in ds) if (name == '__init__' or name[0] != '_') \ - and _ismod(obj)): - obtained = _extract_tags(submodule) - tags += [tag for tag in obtained if not any(tag is x for x in tags)] - del obtained - - # Extract the tags from the current module. - - for tag in (obj for name, obj in ((nm, getattr(module, nm)) for nm in ds) \ - if name[0] != '_' and _isclass(obj) and issubclass(obj, _TextoutTag)): - tags.append(tag) - - return tags - -_tags = _extract_tags(__import__("builtin", \ - {'__name__': __name__ + '.__init__'}, level=1)) -_aliases = {alias: tag for alias, tag in \ - [(alias, tag) for tag in _tags for alias in tag.aliases]} - -# --- -# Function to get a tag. -# --- - -def get_tag(name, value, output_type = 'html', tweaks = {}): - """ Find a tag using its name. """ - - try: - als = _aliases[name] - als = als(name, value, output_type, tweaks) - return als - except: - return None - -# End of file. diff --git a/textoutpc/translate.py b/textoutpc/translate.py index 2ec70cb..ac3e623 100755 --- a/textoutpc/translate.py +++ b/textoutpc/translate.py @@ -10,14 +10,20 @@ import string as _string from copy import deepcopy as _deepcopy from html import escape as _htmlescape +from importlib import import_module as _importmod + from .tags import TextoutBlockTag as _TextoutBlockTag, \ - TextoutParagraphTag as _TextoutParagraphTag, get_tag as _get_tag + TextoutParagraphTag as _TextoutParagraphTag, TextoutTags as _Tags from .stream import TextoutStream as _TextoutStream from .smileys import htmlsmileys as _htmlsmileys from .urls import htmlurls as _htmlurls __all__ = ["Translator"] +# Builtin tags. + +_builtin_tags = _Tags(_importmod('..builtin_tags', __name__)) + # --- # Tweaks interface. # --- @@ -133,7 +139,8 @@ class Translator: You can even chain calls as the `process()` method returns the output stream object. """ - def __init__(self, inp, outp, output_type = 'html', tweaks = {}): + def __init__(self, inp, outp, output_type = 'html', \ + tweaks = {}, tags = _builtin_tags): """ Initializer. """ if not output_type in ('html', 'lightscript'): @@ -141,6 +148,7 @@ class Translator: self.output_type = output_type self.tweaks = _TweaksDictionary(tweaks) + self.tags = tags self.inp = inp self.outp = outp @@ -540,7 +548,7 @@ class Translator: # Then we want to end the tags, and reset them in case we're going # to use them. - self.queue = inlines + blocks + self.queue = inlines[::-1] + blocks[::-1] while self.queue: dat = self.queue.pop(0) tag = dat.tag @@ -665,8 +673,8 @@ class Translator: # Get the initialized tag with the name and value. # If the tag is unknown, output the full thing and just go on. - tag = _get_tag(tagdata.name, tagdata.value, self.output_type, - self.tweaks) + tag = self.tags.get_tag(tagdata.name, tagdata.value, + self.output_type, self.tweaks) if not tag: self.put_text(tagdata.full) continue