The new woob repository is here: https://gitlab.com/woob/woob. This gitlab will be removed soon.

Commit 18d41565 authored by Vincent A's avatar Vincent A

tools: add a cookiecutter template for scaffolding modules

parent 1bffc216
Woob module cookiecutter template
=================================
This is a basic template for scaffolding woob modules with cookiecutter.
How to use
----------
Run cookiecutter:
cookiecutter -o ../../modules .
It will ask a few questions:
full_name [Your Name]:
email [yourmail@example.com]:
site_url [https://example.com]:
site_name [Example]:
capability [CapSomething]:
module_name [twitter]:
class_prefix [TwitterSimple]:
year [2021]:
Develop by editing files in `../modules/your_module/*.py`.
Don't forget to let woob detect your module:
woob update
Create an instance of your module:
[my_backend]
_module = my_module
login = something
password =
Then you can test your module with the appropriate command:
woob something -d -b my_backend
Requirements
------------
This template requires at least cookiecutter 1.7.1.
{
"full_name": "Your Name",
"email": "yourmail@example.com",
"site_url": "https://example.com",
"site_name": "Example",
"capability": "CapSomething",
"module_name": "{{cookiecutter.site_name | slugify | replace('-', '_')}}",
"class_prefix": "{{cookiecutter.module_name | replace('_', ' ') | title | replace(' ', '')}}",
"year": "{% now 'utc', '%Y' %}",
"_extensions": [
"jinja2_time.TimeExtension",
"cookiecutter.extensions.SlugifyExtension"
]
}
# -*- coding: utf-8 -*-
# Copyright(C) {{cookiecutter.year}} {{cookiecutter.full_name}}
#
# This file is part of a woob module.
#
# This woob module 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.
#
# This woob module 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 this woob module. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from .module import {{cookiecutter.class_prefix}}Module
__all__ = ["{{cookiecutter.class_prefix}}Module"]
# -*- coding: utf-8 -*-
# Copyright(C) {{cookiecutter.year}} {{cookiecutter.full_name}}
#
# This file is part of a woob module.
#
# This woob module 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.
#
# This woob module 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 this woob module. If not, see <http://www.gnu.org/licenses/>.
# flake8: compatible
from __future__ import unicode_literals
from woob.browser import LoginBrowser, URL, need_login
from woob.exceptions import BrowserIncorrectPassword
from .pages import (
LoginPage, SomethingPage,
)
class {{cookiecutter.class_prefix}}Browser(LoginBrowser):
BASEURL = "{{cookiecutter.site_url}}"
login = URL(r"/login", LoginPage)
something = URL(r"/something", SomethingPage)
def do_login(self):
self.login.go()
self.page.do_login(self.username, self.password)
if self.page.something():
raise BrowserIncorrectPassword()
@need_login
def iter_something(self):
self.something.go()
return self.page.iter_something()
# -*- coding: utf-8 -*-
# Copyright(C) {{cookiecutter.year}} {{cookiecutter.full_name}}
#
# This file is part of a woob module.
#
# This woob module 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.
#
# This woob module 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 this woob module. If not, see <http://www.gnu.org/licenses/>.
# flake8: compatible
from __future__ import unicode_literals
from woob.capabilities.{{cookiecutter.capability | replace('Cap', '') | lower}} import {{cookiecutter.capability}}
from woob.tools.backend import Module, BackendConfig
from woob.tools.value import ValueBackendPassword
from .browser import {{cookiecutter.class_prefix}}Browser
__all__ = ["{{cookiecutter.class_prefix}}Module"]
class {{cookiecutter.class_prefix}}Module(Module, {{cookiecutter.capability}}):
NAME = "{{cookiecutter.module_name}}"
DESCRIPTION = "{{cookiecutter.site_name}}"
MAINTAINER = "{{cookiecutter.full_name}}"
EMAIL = "{{cookiecutter.email}}"
LICENSE = "LGPLv3+"
VERSION = "3.1"
BROWSER = {{cookiecutter.class_prefix}}Browser
CONFIG = BackendConfig(
ValueBackendPassword("login", label="Username", masked=False),
ValueBackendPassword("password", label="Password"),
)
def create_default_browser(self):
return self.create_browser(
self.config["login"].get(),
self.config["password"].get()
)
def iter_something(self):
return self.browser.iter_something()
# -*- coding: utf-8 -*-
# Copyright(C) {{cookiecutter.year}} {{cookiecutter.full_name}}
#
# This file is part of a woob module.
#
# This woob module 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.
#
# This woob module 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 this woob module. If not, see <http://www.gnu.org/licenses/>.
# flake8: compatible
from __future__ import unicode_literals
from woob.browser.elements import method, ListElement, ItemElement
from woob.browser.filters.html import AbsoluteLink
from woob.browser.filters.standard import (
CleanText, CleanDecimal, Date,
)
from woob.browser.pages import LoggedPage, HTMLPage
class LoginPage(HTMLPage):
def login(self, username, password):
form = self.get_form(id="login")
form["login"] = username
form["password"] = password
form.submit()
class SomethingPage(LoggedPage, HTMLPage):
@method
class iter_something(ListElement):
item_xpath = "//div[@id='something']"
class item(ItemElement):
klass = Something
obj_label = CleanText(".//span[has-class('col-label')]")
obj_price = CleanDecimal.SI(".//span[has-class('col-amount')]")
obj_date = Date(CleanText(".//span[has-class('col-date')]"))
obj_url = AbsoluteLink(".//a")
# -*- coding: utf-8 -*-
# Copyright(C) {{cookiecutter.year}} {{cookiecutter.full_name}}
#
# This file is part of a woob module.
#
# This woob module 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.
#
# This woob module 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 this woob module. If not, see <http://www.gnu.org/licenses/>.
# flake8: compatible
from woob.tools.test import BackendTest
class TwitterTest(BackendTest):
MODULE = "{{cookiecutter.module_name}}"
def test_something(self):
n = -1
for obj, n in zip(self.backend.iter_something(), range(20)):
assert obj.label
assert obj.price
assert obj.url.startswith(self.backend.browser.BASEURL)
assert n > -1
......@@ -10,7 +10,7 @@ MODULE_FILES=$(git ls-files modules|grep '\.py$')
# Takes PYFILES from env, if empty use all git tracked files
: ${PYFILES:=}
if [ -z "${PYFILES}" ]; then
PYFILES="$(git ls-files | grep '^scripts\|\.py$'|grep -v boilerplate_data|grep -v stable_backport_data|grep -v '^modules'|grep -v '^contrib')"
PYFILES="$(git ls-files | grep '^scripts\|\.py$'|grep -v boilerplate_data|grep -v stable_backport_data|grep -v '^modules'|grep -v '^contrib'|grep -v cookiecutter)"
PYFILES="$PYFILES $MODULE_FILES"
fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment