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()