baseweb-plugin-template


Namebaseweb-plugin-template JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/christophevg/baseweb-plugin-template
Summaryan example baseweb plugin
upload_time2023-09-17 13:13:10
maintainer
docs_urlNone
authorChristophe VG
requires_python
licenseMIT
keywords example baseweb plugin
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # baseweb plugin template

> How to create extensions/plugins to baseweb, and create a more complete application setup...

[![Latest Version on PyPI](https://img.shields.io/pypi/v/baseweb-plugin-template.svg)](https://pypi.python.org/pypi/baseweb-plugin-template/)
[![Supported Implementations](https://img.shields.io/pypi/pyversions/baseweb-plugin-template.svg)](https://pypi.python.org/pypi/baseweb-plugin-template/)
[![basweb](https://img.shields.io/badge/baseweb-v0.1.x-blue.svg)](https://pypi.org/project/baseweb/)
[![Built with PyPi Template](https://img.shields.io/badge/PyPi_Template-v0.3.2-blue.svg)](https://github.com/christophevg/pypi-template)

## Rationale

To avoid implementing too much personal taste into baseweb, adding application-specifics should and can be done by following a plugin-approach, where these additions are packaged as additions, wrapping and extending the core basewen functionality.

This repository acts as a guide on how to extend baseweb in such a non-intrusive way, by creating a partial baseweb application that implements additional functionality on top of baseweb one commonly would like to have, thus avoiding a lot of boilerplate coding during the first commit phase of a new project.

This repository can therefore be considered a complement/sibbling of the [baseweb-demo repository](https://github.com/christophevg/baseweb-demo), showing how to create your own baseweb plugin.

## The Actual Steps

Let's start with my standard Python-based project setup:

```console
% mkdir baseweb-plugin-template
% cd baseweb-plugin-template
% git init
% pyenv virtualenv baseweb-plugin-template
% pyenv local baseweb-plugin-template
% pip install -U pip
```

Next, since I want this to be a Python package, installable from [https://pypi.org](https://pypi.org), I use my own [https://pypi.org/project/pypi-template/](https://pypi.org/project/pypi-template/) to setup all the boilerplate:

```console
% pip install pypi-template
% pypi-template init
A description for the package: an example baseweb plugin
Select classifiers: Programming Language :: Python
Select classifiers: Programming Language :: Python :: 3
Select classifiers: Intended Audience :: Developers
Select classifiers: Development Status :: 4 - Beta
Select classifiers: License :: OSI Approved :: MIT License
Select classifiers: Environment :: Plugins
Select classifiers: Environment :: Web Environment
Select classifiers: 
Select console scripts: 
First year of publication: 2023
Github account: christophevg
Github repo name: baseweb-plugin-template
Keywords describing the package: example baseweb plugin
License: MIT
Package module name: baseweb_plugin_template
Package name: basweb-plugin-template
Package tagline: an example baseweb plugin
Package title: an example baseweb plugin
Select requires: baseweb
...
```

That gives us a complete project setup. For this repo, I'm going to exclude some of the baseweb-managed parts, since I'll be documenting it simply in this README, won't be implementing any tests, and of course I'll be changing the module itself:

```console
% pypi-template ignore docs ignore .readthedocs.yaml ignore .github ignore tests ignore tox.ini ignore "(package_module_name)" ignore MANIFEST.in apply
```

### The Plugin

This Template plugin will implement some typical boilerplate every baseweb app requires, thus avoiding the tedious work. The `__init__.py` of the plugin looks like this:

```python
__version__ = "0.0.1"

import logging
logger = logging.getLogger(__name__)

import os

LOG_LEVEL = os.environ.get("LOG_LEVEL") or "INFO"
FORMAT    = "[%(name)s] [%(levelname)s] %(message)s"
DATEFMT   = "%Y-%m-%d %H:%M:%S %z"

logging.basicConfig(level=LOG_LEVEL, format=FORMAT, datefmt=DATEFMT)
formatter = logging.Formatter(FORMAT, DATEFMT)
logging.getLogger().handlers[0].setFormatter(formatter)

# "silence" lower-level modules
for module in [ "gunicorn.error", "baseweb.socketio", "baseweb.web", "baseweb.interface" ]:
  module_logger = logging.getLogger(module)
  module_logger.setLevel(logging.WARN)
  if len(module_logger.handlers) > 0:
    module_logger.handlers[0].setFormatter(formatter)

from baseweb.interface import register_component, register_static_folder

HERE = os.path.dirname(__file__)

register_static_folder(os.path.join(HERE, "static"))

COMPONENTS = os.path.join(HERE, "components")
for component in [
  "page",
]:
  register_component(f"{component}.js", COMPONENTS)

# expose baseweb server and perform additional configuration
from baseweb.web import server

server.config["TEMPLATES_AUTO_RELOAD"] = True
server.config["SECRET_KEY"] = os.environ.get("APP_SECRET_KEY", default="local")

logger.info("✅ everything loaded...")
```

In the `static` folder, we add and `images` folder, with `baseball.png` in it and we create a `components` folder with `page.js`, containing:

```javascript
Vue.component("Page", {
  template: `
<div style="margin:20px;">
  <img src="/app/static/images/baseball.png" style="float:left"/>
  <slot/>
</div>`
});
```

So, all in all, this plugin provides some basic logging setup and a `Page` component that adds an image of a baseball to your wrapped content.

> don't forget to include the `components` and `static` folders in your `MANIFEST.in`, else these not-py files won't be included - this is also the reason why we asked pypi-template to ignore the MANIFEST.in file, since we need to apply our own changes to it:

```
include .github/README.md
recursive-include baseweb_plugin_template/components *
recursive-include baseweb_plugin_template/static *
global-exclude __pycache__
global-exclude *.py[co]

```

### Testing the template

We can now test our plugin by using it to implement a simple "Hello World"-style baseweb application, consisting of an `app.py`:

```python
import os

from baseweb_plugin_template import server
from baseweb.interface import register_component

register_component("hello.js", os.path.dirname(__file__))
```

and a `hello.js`:

```javascript
var Hello = {
  template : `
<Page>
  <h1>Hello baseweb plugin world!</h1>
</Page>
`,
  navigation: {
    icon:    "info",
    text:    "Hello",
    path:    "/",
    index:   1
  }
};

Navigation.add(Hello);
```

You can find these files also in the `example` folder. Running it consists of setting up a local virtual environment, installing the plugin and running it...

```console
% cd example
% pyenv virtualenv baseweb-plugin-template-test
% pyenv local baseweb-plugin-template-test
(baseweb-plugin-template-test) % pip install -r requirements.txt
(baseweb-plugin-template-test) % pip install ../
(baseweb-plugin-template-test) % gunicorn -w1 -k eventlet app:server 
[2023-09-17 10:11:06 +0200] [21992] [INFO] Starting gunicorn 20.1.0
[2023-09-17 10:11:06 +0200] [21992] [INFO] Listening at: http://127.0.0.1:8000 (21992)
[2023-09-17 10:11:06 +0200] [21992] [INFO] Using worker: eventlet
[2023-09-17 10:11:06 +0200] [22019] [INFO] Booting worker with pid: 22019
[baseweb] [INFO] 
 _                                 _     
| |__   __ _ ___  _____      _____| |__  
| '_ \ / _` / __|/ _ \ \ /\ / / _ \ '_ \ 
| |_) | (_| \__ \  __/\ V  V /  __/ |_) |
|_.__/ \__,_|___/\___| \_/\_/ \___|_.__/  0.1.4
[baseweb.config] [INFO] {
  "version": "0.1.4",
  "name": "example",
  "short_name": "Example",
  "author": "Unknown Author",
  "description": "A baseweb app",
  "color_scheme": "dark",
  "color": "rgb(21, 101, 192)",
  "color_name": "blue darken-3",
  "background_color": "rgb(21, 101, 192)",
  "style": "web",
  "icon": null,
  "socketio": true,
  "favicon_support": false,
  "favicon_mask_icon_color": null,
  "favicon_msapp_tile_color": null
}
[baseweb_plugin_template] [INFO] ✅ everything loaded...
```

![Hello Baseweb Plugin World](https://raw.githubusercontent.com/christophevg/baseweb-plugin-template/master/media/hello-baseweb-plugin-world.png)



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/christophevg/baseweb-plugin-template",
    "name": "baseweb-plugin-template",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "example baseweb plugin",
    "author": "Christophe VG",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/18/b2/ca4482c87d685612250c543bf43e22b4b8884ca1703846da7cf4bd285da4/baseweb-plugin-template-0.1.0.tar.gz",
    "platform": null,
    "description": "# baseweb plugin template\n\n> How to create extensions/plugins to baseweb, and create a more complete application setup...\n\n[![Latest Version on PyPI](https://img.shields.io/pypi/v/baseweb-plugin-template.svg)](https://pypi.python.org/pypi/baseweb-plugin-template/)\n[![Supported Implementations](https://img.shields.io/pypi/pyversions/baseweb-plugin-template.svg)](https://pypi.python.org/pypi/baseweb-plugin-template/)\n[![basweb](https://img.shields.io/badge/baseweb-v0.1.x-blue.svg)](https://pypi.org/project/baseweb/)\n[![Built with PyPi Template](https://img.shields.io/badge/PyPi_Template-v0.3.2-blue.svg)](https://github.com/christophevg/pypi-template)\n\n## Rationale\n\nTo avoid implementing too much personal taste into baseweb, adding application-specifics should and can be done by following a plugin-approach, where these additions are packaged as additions, wrapping and extending the core basewen functionality.\n\nThis repository acts as a guide on how to extend baseweb in such a non-intrusive way, by creating a partial baseweb application that implements additional functionality on top of baseweb one commonly would like to have, thus avoiding a lot of boilerplate coding during the first commit phase of a new project.\n\nThis repository can therefore be considered a complement/sibbling of the [baseweb-demo repository](https://github.com/christophevg/baseweb-demo), showing how to create your own baseweb plugin.\n\n## The Actual Steps\n\nLet's start with my standard Python-based project setup:\n\n```console\n% mkdir baseweb-plugin-template\n% cd baseweb-plugin-template\n% git init\n% pyenv virtualenv baseweb-plugin-template\n% pyenv local baseweb-plugin-template\n% pip install -U pip\n```\n\nNext, since I want this to be a Python package, installable from [https://pypi.org](https://pypi.org), I use my own [https://pypi.org/project/pypi-template/](https://pypi.org/project/pypi-template/) to setup all the boilerplate:\n\n```console\n% pip install pypi-template\n% pypi-template init\nA description for the package: an example baseweb plugin\nSelect classifiers: Programming Language :: Python\nSelect classifiers: Programming Language :: Python :: 3\nSelect classifiers: Intended Audience :: Developers\nSelect classifiers: Development Status :: 4 - Beta\nSelect classifiers: License :: OSI Approved :: MIT License\nSelect classifiers: Environment :: Plugins\nSelect classifiers: Environment :: Web Environment\nSelect classifiers: \nSelect console scripts: \nFirst year of publication: 2023\nGithub account: christophevg\nGithub repo name: baseweb-plugin-template\nKeywords describing the package: example baseweb plugin\nLicense: MIT\nPackage module name: baseweb_plugin_template\nPackage name: basweb-plugin-template\nPackage tagline: an example baseweb plugin\nPackage title: an example baseweb plugin\nSelect requires: baseweb\n...\n```\n\nThat gives us a complete project setup. For this repo, I'm going to exclude some of the baseweb-managed parts, since I'll be documenting it simply in this README, won't be implementing any tests, and of course I'll be changing the module itself:\n\n```console\n% pypi-template ignore docs ignore .readthedocs.yaml ignore .github ignore tests ignore tox.ini ignore \"(package_module_name)\" ignore MANIFEST.in apply\n```\n\n### The Plugin\n\nThis Template plugin will implement some typical boilerplate every baseweb app requires, thus avoiding the tedious work. The `__init__.py` of the plugin looks like this:\n\n```python\n__version__ = \"0.0.1\"\n\nimport logging\nlogger = logging.getLogger(__name__)\n\nimport os\n\nLOG_LEVEL = os.environ.get(\"LOG_LEVEL\") or \"INFO\"\nFORMAT    = \"[%(name)s] [%(levelname)s] %(message)s\"\nDATEFMT   = \"%Y-%m-%d %H:%M:%S %z\"\n\nlogging.basicConfig(level=LOG_LEVEL, format=FORMAT, datefmt=DATEFMT)\nformatter = logging.Formatter(FORMAT, DATEFMT)\nlogging.getLogger().handlers[0].setFormatter(formatter)\n\n# \"silence\" lower-level modules\nfor module in [ \"gunicorn.error\", \"baseweb.socketio\", \"baseweb.web\", \"baseweb.interface\" ]:\n  module_logger = logging.getLogger(module)\n  module_logger.setLevel(logging.WARN)\n  if len(module_logger.handlers) > 0:\n    module_logger.handlers[0].setFormatter(formatter)\n\nfrom baseweb.interface import register_component, register_static_folder\n\nHERE = os.path.dirname(__file__)\n\nregister_static_folder(os.path.join(HERE, \"static\"))\n\nCOMPONENTS = os.path.join(HERE, \"components\")\nfor component in [\n  \"page\",\n]:\n  register_component(f\"{component}.js\", COMPONENTS)\n\n# expose baseweb server and perform additional configuration\nfrom baseweb.web import server\n\nserver.config[\"TEMPLATES_AUTO_RELOAD\"] = True\nserver.config[\"SECRET_KEY\"] = os.environ.get(\"APP_SECRET_KEY\", default=\"local\")\n\nlogger.info(\"\u2705 everything loaded...\")\n```\n\nIn the `static` folder, we add and `images` folder, with `baseball.png` in it and we create a `components` folder with `page.js`, containing:\n\n```javascript\nVue.component(\"Page\", {\n  template: `\n<div style=\"margin:20px;\">\n  <img src=\"/app/static/images/baseball.png\" style=\"float:left\"/>\n  <slot/>\n</div>`\n});\n```\n\nSo, all in all, this plugin provides some basic logging setup and a `Page` component that adds an image of a baseball to your wrapped content.\n\n> don't forget to include the `components` and `static` folders in your `MANIFEST.in`, else these not-py files won't be included - this is also the reason why we asked pypi-template to ignore the MANIFEST.in file, since we need to apply our own changes to it:\n\n```\ninclude .github/README.md\nrecursive-include baseweb_plugin_template/components *\nrecursive-include baseweb_plugin_template/static *\nglobal-exclude __pycache__\nglobal-exclude *.py[co]\n\n```\n\n### Testing the template\n\nWe can now test our plugin by using it to implement a simple \"Hello World\"-style baseweb application, consisting of an `app.py`:\n\n```python\nimport os\n\nfrom baseweb_plugin_template import server\nfrom baseweb.interface import register_component\n\nregister_component(\"hello.js\", os.path.dirname(__file__))\n```\n\nand a `hello.js`:\n\n```javascript\nvar Hello = {\n  template : `\n<Page>\n  <h1>Hello baseweb plugin world!</h1>\n</Page>\n`,\n  navigation: {\n    icon:    \"info\",\n    text:    \"Hello\",\n    path:    \"/\",\n    index:   1\n  }\n};\n\nNavigation.add(Hello);\n```\n\nYou can find these files also in the `example` folder. Running it consists of setting up a local virtual environment, installing the plugin and running it...\n\n```console\n% cd example\n% pyenv virtualenv baseweb-plugin-template-test\n% pyenv local baseweb-plugin-template-test\n(baseweb-plugin-template-test) % pip install -r requirements.txt\n(baseweb-plugin-template-test) % pip install ../\n(baseweb-plugin-template-test) % gunicorn -w1 -k eventlet app:server \n[2023-09-17 10:11:06 +0200] [21992] [INFO] Starting gunicorn 20.1.0\n[2023-09-17 10:11:06 +0200] [21992] [INFO] Listening at: http://127.0.0.1:8000 (21992)\n[2023-09-17 10:11:06 +0200] [21992] [INFO] Using worker: eventlet\n[2023-09-17 10:11:06 +0200] [22019] [INFO] Booting worker with pid: 22019\n[baseweb] [INFO] \n _                                 _     \n| |__   __ _ ___  _____      _____| |__  \n| '_ \\ / _` / __|/ _ \\ \\ /\\ / / _ \\ '_ \\ \n| |_) | (_| \\__ \\  __/\\ V  V /  __/ |_) |\n|_.__/ \\__,_|___/\\___| \\_/\\_/ \\___|_.__/  0.1.4\n[baseweb.config] [INFO] {\n  \"version\": \"0.1.4\",\n  \"name\": \"example\",\n  \"short_name\": \"Example\",\n  \"author\": \"Unknown Author\",\n  \"description\": \"A baseweb app\",\n  \"color_scheme\": \"dark\",\n  \"color\": \"rgb(21, 101, 192)\",\n  \"color_name\": \"blue darken-3\",\n  \"background_color\": \"rgb(21, 101, 192)\",\n  \"style\": \"web\",\n  \"icon\": null,\n  \"socketio\": true,\n  \"favicon_support\": false,\n  \"favicon_mask_icon_color\": null,\n  \"favicon_msapp_tile_color\": null\n}\n[baseweb_plugin_template] [INFO] \u2705 everything loaded...\n```\n\n![Hello Baseweb Plugin World](https://raw.githubusercontent.com/christophevg/baseweb-plugin-template/master/media/hello-baseweb-plugin-world.png)\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "an example baseweb plugin",
    "version": "0.1.0",
    "project_urls": {
        "Homepage": "https://github.com/christophevg/baseweb-plugin-template"
    },
    "split_keywords": [
        "example",
        "baseweb",
        "plugin"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "af39b09b9e7b2746f66cf9e35abba5a4563d02469fd697743182229419158749",
                "md5": "fbdc07b6015a3f2d1905df49101f223f",
                "sha256": "86dcb578edcf20a0d0cb66ab5d067982d9568cc62056aa2d54a374d5d849a7ec"
            },
            "downloads": -1,
            "filename": "baseweb_plugin_template-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fbdc07b6015a3f2d1905df49101f223f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 16651,
            "upload_time": "2023-09-17T13:13:08",
            "upload_time_iso_8601": "2023-09-17T13:13:08.998368Z",
            "url": "https://files.pythonhosted.org/packages/af/39/b09b9e7b2746f66cf9e35abba5a4563d02469fd697743182229419158749/baseweb_plugin_template-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "18b2ca4482c87d685612250c543bf43e22b4b8884ca1703846da7cf4bd285da4",
                "md5": "8971e13ef359a9015a7c54eb7ac2b7f4",
                "sha256": "70ee8b80456e555ee0e06d3855a4175cf800cf7a05f1033cded623be298590a6"
            },
            "downloads": -1,
            "filename": "baseweb-plugin-template-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "8971e13ef359a9015a7c54eb7ac2b7f4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 19105,
            "upload_time": "2023-09-17T13:13:10",
            "upload_time_iso_8601": "2023-09-17T13:13:10.673839Z",
            "url": "https://files.pythonhosted.org/packages/18/b2/ca4482c87d685612250c543bf43e22b4b8884ca1703846da7cf4bd285da4/baseweb-plugin-template-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-17 13:13:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "christophevg",
    "github_project": "baseweb-plugin-template",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "baseweb-plugin-template"
}
        
Elapsed time: 2.35533s