diff --git a/tools/boilerplate/__init__.py b/tools/boilerplate/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/boilerplate/boilerplate.py b/tools/boilerplate/boilerplate.py new file mode 100755 index 0000000000000000000000000000000000000000..d11ca165374f379e7c420ec605dcdf67c7866665 --- /dev/null +++ b/tools/boilerplate/boilerplate.py @@ -0,0 +1,73 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright(C) 2013-2019 Laurent Bachelier, Sébastien Jean +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with weboob. If not, see . + +from __future__ import print_function + +import argparse +import inspect +import subprocess +import os +import sys + + +from importlib import import_module + +BOILERPLATE_PATH = os.getenv( + 'BOILERPLATE_PATH', + os.path.realpath(os.path.join(os.path.dirname(__file__), 'boilerplate_data'))) + +sys.path.append(os.path.dirname(__file__)) +sys.path.append(BOILERPLATE_PATH) + + +def u8(s): + if isinstance(s, bytes): + return s.decode('utf-8') + return s + + +def gitconfig(entry): + return u8(subprocess.check_output('git config -z --get %s' % entry, shell=True)[:-1]) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '-a', '--author', + default=gitconfig('user.name'), type=u8) + parser.add_argument( + '-e', '--email', + default=gitconfig('user.email'), type=u8) + subparsers = parser.add_subparsers() + + recipes_module = import_module('recipes', package='boilerplate_data') + + for k, v in recipes_module.__dict__.items(): + if inspect.isclass(v) and not k.startswith('_'): + v.configure_subparser(subparsers) + + args = parser.parse_args() + + recipe = args.recipe(args) + recipe.generate() + + +if __name__ == '__main__': + main() diff --git a/tools/boilerplate_data/base_browser.py b/tools/boilerplate/boilerplate_data/base_browser.pyt similarity index 95% rename from tools/boilerplate_data/base_browser.py rename to tools/boilerplate/boilerplate_data/base_browser.pyt index ebe34561ccfc61eba192133e8d1e537c7dd5da68..6b43da13999957b3a33df04ce2060da8ad0377ac 100644 --- a/tools/boilerplate_data/base_browser.py +++ b/tools/boilerplate/boilerplate_data/base_browser.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.browser import ${'LoginBrowser, need_login' if r.login else 'PagesBrowser'}, URL from .pages import Page1, Page2 diff --git a/tools/boilerplate_data/base_module.py b/tools/boilerplate/boilerplate_data/base_module.pyt similarity index 92% rename from tools/boilerplate_data/base_module.py rename to tools/boilerplate/boilerplate_data/base_module.pyt index db7e05d7a05b4b8e197670480653a1fc61559571..b95c442e354e3282f425904165db942946ea9bb3 100644 --- a/tools/boilerplate_data/base_module.py +++ b/tools/boilerplate/boilerplate_data/base_module.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.tools.backend import Module from .browser import ${r.classname}Browser diff --git a/tools/boilerplate_data/base_pages.py b/tools/boilerplate/boilerplate_data/base_pages.pyt similarity index 88% rename from tools/boilerplate_data/base_pages.py rename to tools/boilerplate/boilerplate_data/base_pages.pyt index 98ca6e28e7031efd9dac181949d01009fb8378a6..72fc956e109df9025e57aaf9a375c52796d38979 100644 --- a/tools/boilerplate_data/base_pages.py +++ b/tools/boilerplate/boilerplate_data/base_pages.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.browser.pages import HTMLPage diff --git a/tools/boilerplate_data/base_test.py b/tools/boilerplate/boilerplate_data/base_test.pyt similarity index 78% rename from tools/boilerplate_data/base_test.py rename to tools/boilerplate/boilerplate_data/base_test.pyt index fe9f97ac606e0447bb68355df45990f65bfb7409..c6264ed676cd1b570f6226c20dc9201b458f5913 100644 --- a/tools/boilerplate_data/base_test.py +++ b/tools/boilerplate/boilerplate_data/base_test.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.tools.test import BackendTest diff --git a/tools/boilerplate_data/cap_module.py b/tools/boilerplate/boilerplate_data/cap_module.pyt similarity index 96% rename from tools/boilerplate_data/cap_module.py rename to tools/boilerplate/boilerplate_data/cap_module.pyt index 0c22299cfb29d4022802b047d1081fb41fed9dc1..3c7c725c4424d1e9f646022b06ead97e8cec1252 100644 --- a/tools/boilerplate_data/cap_module.py +++ b/tools/boilerplate/boilerplate_data/cap_module.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.tools.backend import Module${', BackendConfig' if r.login else ''} % if login: from weboob.tools.value import Value, ValueBackendPassword diff --git a/tools/boilerplate_data/comic_module.py b/tools/boilerplate/boilerplate_data/comic_module.pyt similarity index 96% rename from tools/boilerplate_data/comic_module.py rename to tools/boilerplate/boilerplate_data/comic_module.pyt index 93630480d0bb41579512b8be7391271295030c82..500a2543e6cfb148e99916dd46f94ce29f2dfd65 100644 --- a/tools/boilerplate_data/comic_module.py +++ b/tools/boilerplate/boilerplate_data/comic_module.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderModule, DisplayPage diff --git a/tools/boilerplate_data/comic_test.py b/tools/boilerplate/boilerplate_data/comic_test.pyt similarity index 89% rename from tools/boilerplate_data/comic_test.py rename to tools/boilerplate/boilerplate_data/comic_test.pyt index 739fc9e79bcb2231d96a5e616022d19ec862a78d..3fee49b7d9548c4c60b4fe4c792e0a3d16e946c6 100644 --- a/tools/boilerplate_data/comic_test.py +++ b/tools/boilerplate/boilerplate_data/comic_test.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from weboob.tools.capabilities.gallery.genericcomicreadertest import GenericComicReaderTest diff --git a/tools/boilerplate_data/init.py b/tools/boilerplate/boilerplate_data/init.pyt similarity index 72% rename from tools/boilerplate_data/init.py rename to tools/boilerplate/boilerplate_data/init.pyt index b07a2b59acfec1549b861cffb25f8a90613dcdbd..6607be120dd65a66c599125e781c29e5225e6548 100644 --- a/tools/boilerplate_data/init.py +++ b/tools/boilerplate/boilerplate_data/init.pyt @@ -1,4 +1,4 @@ -<%inherit file="layout.py"/> +<%inherit file="layout.pyt"/> from .module import ${r.classname}Module diff --git a/tools/boilerplate_data/layout.py b/tools/boilerplate/boilerplate_data/layout.pyt similarity index 100% rename from tools/boilerplate_data/layout.py rename to tools/boilerplate/boilerplate_data/layout.pyt diff --git a/tools/boilerplate.py b/tools/boilerplate/boilerplate_data/recipes.py old mode 100755 new mode 100644 similarity index 60% rename from tools/boilerplate.py rename to tools/boilerplate/boilerplate_data/recipes.py index f322f06cf8de1baf64943e09566c94ae66666422..a7ed0a2da976d4775369a19a7c4b93459cb551d2 --- a/tools/boilerplate.py +++ b/tools/boilerplate/boilerplate_data/recipes.py @@ -1,7 +1,7 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -# Copyright(C) 2013 Laurent Bachelier +# Copyright(C) 2013-2019 Laurent Bachelier, Sébastien Jean # # This file is part of weboob. # @@ -20,82 +20,13 @@ from __future__ import print_function -import argparse -import subprocess -import datetime import importlib -import os import sys -import codecs -from mako.lookup import TemplateLookup -MODULE_PATH = os.getenv( - 'MODULE_PATH', - os.path.realpath(os.path.join(os.path.dirname(__file__), '../modules'))) -TEMPLATE_PATH = os.getenv( - 'TEMPLATE_PATH', - os.path.realpath(os.path.join(os.path.dirname(__file__), 'boilerplate_data'))) -VERSION = '1.5' +from recipe import _Recipe -TEMPLATES = TemplateLookup(directories=[TEMPLATE_PATH]) - -def u8(s): - if isinstance(s, bytes): - return s.decode('utf-8') - return s - - -def gitconfig(entry): - return u8(subprocess.check_output('git config -z --get %s' % entry, shell=True)[:-1]) - - -def write(target, contents): - if not os.path.isdir(os.path.dirname(target)): - os.makedirs(os.path.dirname(target)) - if os.path.exists(target): - print("%s already exists." % target, file=sys.stderr) - sys.exit(4) - with codecs.open(target, mode='w', encoding='utf-8') as f: - f.write(contents) - print('Created %s' % target) - - -class Recipe(object): - @classmethod - def configure_subparser(cls, subparsers): - subparser = subparsers.add_parser(cls.NAME) - subparser.add_argument('name', help='Module name') - subparser.set_defaults(recipe=cls) - return subparser - - def __init__(self, args): - self.name = args.name.lower().replace(' ', '') - self.classname = args.name.title().replace(' ', '') - self.year = datetime.date.today().year - self.author = args.author - self.email = args.email - self.version = VERSION - self.login = False - - def write(self, filename, contents): - return write(os.path.join(MODULE_PATH, self.name, filename), contents) - - def template(self, name, **kwargs): - if '.' not in name: - name += '.py' - return TEMPLATES.get_template(name) \ - .render(r=self, - # workaround, as it's also a mako directive - coding='# -*- coding: utf-8 -*-', - login=self.login, - **kwargs) - - def generate(self): - raise NotImplementedError() - - -class BaseRecipe(Recipe): +class BaseRecipe(_Recipe): NAME = 'base' def generate(self): @@ -106,7 +37,7 @@ def generate(self): self.write('test.py', self.template('base_test')) -class CapRecipe(Recipe): +class CapRecipe(_Recipe): NAME = 'cap' def __init__(self, args): @@ -185,7 +116,7 @@ def generate(self): self.write('test.py', self.template('base_test')) -class ComicRecipe(Recipe): +class ComicRecipe(_Recipe): NAME = 'comic' def generate(self): @@ -193,7 +124,7 @@ def generate(self): self.write('module.py', self.template('comic_module')) -class ComicTestRecipe(Recipe): +class ComicTestRecipe(_Recipe): NAME = 'comic.test' @classmethod @@ -208,26 +139,3 @@ def __init__(self, args): def generate(self): self.write('test.py', self.template('comic_test')) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument( - '-a', '--author', - default=gitconfig('user.name'), type=u8) - parser.add_argument( - '-e', '--email', - default=gitconfig('user.email'), type=u8) - subparsers = parser.add_subparsers() - - recipes = [BaseRecipe, ComicRecipe, ComicTestRecipe, CapRecipe] - for recipe in recipes: - recipe.configure_subparser(subparsers) - - args = parser.parse_args() - - recipe = args.recipe(args) - recipe.generate() - -if __name__ == '__main__': - main() diff --git a/tools/boilerplate/recipe.py b/tools/boilerplate/recipe.py new file mode 100644 index 0000000000000000000000000000000000000000..864160e9fcb1646e841e33a1ea11948ae7964d14 --- /dev/null +++ b/tools/boilerplate/recipe.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Laurent Bachelier +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with weboob. If not, see . + + +from __future__ import print_function +import os +import datetime +import sys +import codecs + +from mako.lookup import TemplateLookup +from weboob import __version__ + + +WEBOOB_MODULES = os.getenv( + 'WEBOOB_MODULES', + os.path.realpath(os.path.join(os.path.dirname(__file__), '../../modules'))) +BOILERPLATE_PATH = os.getenv( + 'BOILERPLATE_PATH', + os.path.realpath(os.path.join(os.path.dirname(__file__), 'boilerplate_data'))) + +TEMPLATES = TemplateLookup(directories=[BOILERPLATE_PATH]) + + +def write(target, contents): + if not os.path.isdir(os.path.dirname(target)): + os.makedirs(os.path.dirname(target)) + if os.path.exists(target): + print("%s already exists." % target, file=sys.stderr) + sys.exit(4) + with codecs.open(target, mode='w', encoding='utf-8') as f: + f.write(contents) + print('Created %s' % target) + + +class _Recipe(object): + @classmethod + def configure_subparser(cls, subparsers): + subparser = subparsers.add_parser(cls.NAME) + subparser.add_argument('name', help='Module name') + subparser.set_defaults(recipe=cls) + return subparser + + def __init__(self, args): + self.name = args.name.lower().replace(' ', '') + self.classname = args.name.title().replace(' ', '') + self.year = datetime.date.today().year + self.author = args.author + self.email = args.email + self.version = __version__ + self.login = False + + def write(self, filename, contents): + return write(os.path.join(WEBOOB_MODULES, self.name, filename), contents) + + def template(self, name, **kwargs): + if '.' not in name: + name += '.pyt' + return TEMPLATES.get_template(name) \ + .render(r=self, + # workaround, as it's also a mako directive + coding='# -*- coding: utf-8 -*-', + login=self.login, + **kwargs) + + def generate(self): + raise NotImplementedError()