Package: baseweb-plugin-template
baseweb plugin templateHow to create extensions/plugins to baseweb, and create a more complete application setup...RationaleTo 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 thebaseweb-demo repository, showing how to create your own baseweb plugin.The Actual StepsLet's start with my standard Python-based project setup:%mkdirbaseweb-plugin-template%cdbaseweb-plugin-template%gitinit%pyenvvirtualenvbaseweb-plugin-template%pyenvlocalbaseweb-plugin-template%pipinstall-UpipNext, since I want this to be a Python package, installable fromhttps://pypi.org, I use my ownhttps://pypi.org/project/pypi-template/to setup all the boilerplate:%pipinstallpypi-template%pypi-templateinitA description for the package: an example baseweb pluginSelect classifiers: Programming Language :: PythonSelect classifiers: Programming Language :: Python :: 3Select classifiers: Intended Audience :: DevelopersSelect classifiers: Development Status :: 4 - BetaSelect classifiers: License :: OSI Approved :: MIT LicenseSelect classifiers: Environment :: PluginsSelect classifiers: Environment :: Web EnvironmentSelect classifiers:Select console scripts:First year of publication: 2023Github account: christophevgGithub repo name: baseweb-plugin-templateKeywords describing the package: example baseweb pluginLicense: MITPackage module name: baseweb_plugin_templatePackage name: basweb-plugin-templatePackage tagline: an example baseweb pluginPackage title: an example baseweb pluginSelect 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:%pypi-templateignoredocsignore.readthedocs.yamlignore.githubignoretestsignoretox.iniignore"(package_module_name)"ignoreMANIFEST.inapplyThe PluginThis Template plugin will implement some typical boilerplate every baseweb app requires, thus avoiding the tedious work. The__init__.pyof the plugin looks like this:__version__="0.0.1"importlogginglogger=logging.getLogger(__name__)importosLOG_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 modulesformodulein["gunicorn.error","baseweb.socketio","baseweb.web","baseweb.interface"]:module_logger=logging.getLogger(module)module_logger.setLevel(logging.WARN)iflen(module_logger.handlers)>0:module_logger.handlers[0].setFormatter(formatter)frombaseweb.interfaceimportregister_component,register_static_folderHERE=os.path.dirname(__file__)register_static_folder(os.path.join(HERE,"static"))COMPONENTS=os.path.join(HERE,"components")forcomponentin["page",]:register_component(f"{component}.js",COMPONENTS)# expose baseweb server and perform additional configurationfrombaseweb.webimportserverserver.config["TEMPLATES_AUTO_RELOAD"]=Trueserver.config["SECRET_KEY"]=os.environ.get("APP_SECRET_KEY",default="local")logger.info("✅ everything loaded...")In thestaticfolder, we add andimagesfolder, withbaseball.pngin it and we create acomponentsfolder withpage.js, containing: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 aPagecomponent that adds an image of a baseball to your wrapped content.don't forget to include thecomponentsandstaticfolders in yourMANIFEST.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 templateWe can now test our plugin by using it to implement a simple "Hello World"-style baseweb application, consisting of anapp.py:importosfrombaseweb_plugin_templateimportserverfrombaseweb.interfaceimportregister_componentregister_component("hello.js",os.path.dirname(__file__))and ahello.js:varHello={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 theexamplefolder. Running it consists of setting up a local virtual environment, installing the plugin and running it...%cdexample%pyenvvirtualenvbaseweb-plugin-template-test%pyenvlocalbaseweb-plugin-template-test(baseweb-plugin-template-test)%pipinstall-rrequirements.txt(baseweb-plugin-template-test)%pipinstall../(baseweb-plugin-template-test)%gunicorn-w1-keventletapp: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...