WebCore
WebCore, the super tiny and blazingly fast modular Python web nanoframework.
Install / Use
/learn @marrow/WebCoreREADME
======= WebCore
© 2006-2019 Alice Bevan-McGregor and contributors.
..
https://github.com/marrow/WebCore
..
|latestversion| |ghtag| |downloads| |masterstatus| |mastercover| |masterreq| |ghwatch| |ghstar|
-
What is WebCore?_ -
Installation_-
Dependencies and Extras_ -
Development Version_
-
-
Basic Concepts_-
Application_ -
Context_ -
Controllers, Endpoints, Dispatch, Oh My!_
-
-
Plugins and Namespaces_ -
Version History_ -
License_
What is WebCore?
WebCore is a nanoframework, a fraction of the size of competing "microframeworks", and culmination of more than ten years of web development experience. It provides a clean API for standard points of extension while strongly encouraging model, view, controller separation. Being less than 400 source lines of code (SLoC; excluding comments and documentation) and containing more comments and lines of documentation than lines of code, WebCore is built to be insanely easy to test, adapt, and use, allowing any developer familiar with programming (not just Python programming) to be able to read and understand the entirety of the framework in an evening.
It is substantially smaller and more efficient than monolithic frameworks such as Django or Pyramid::
from web.core import Application
Application("Hi.").serve('wsgiref')
Really; that's it. (It can be made into one line if you're willing to make the import ugly using __import__.) The
Application class represents a standard Python WSGI application, the rest is up to you to pick the components that
best fit your own needs.
Installation
Installing WebCore is easy, just execute the following in a terminal::
pip install WebCore
Note: We strongly recommend always using a container, virtualization, or sandboxing environment of some kind when
developing using Python; installing things system-wide is yucky (for a variety of reasons) nine times out of ten. We
prefer light-weight virtualenv <https://virtualenv.pypa.io/>, others prefer solutions as
robust as Vagrant <http://www.vagrantup.com>.
If you add WebCore to the install_requires argument of the call to setup() in your application's
setup.py file, WebCore will be automatically installed and made available when your own application or
library is installed. We recommend using "less than" version numbers to ensure there are no unintentional
side-effects when updating. Use WebCore<2.1 to get all bugfixes for the current release, and
WebCore<3.0 to get bugfixes and feature updates while ensuring that large breaking changes are not installed.
Dependencies and Extras
WebCore only depends on the excellent webob <http://webob.org>__ package to provide request, response, and HTTP
status code exception helpers and the marrow.package <https://github.com/marrow/package>__ utility package for plugin
management. All other dependencies will be application dependencies; choice of template engine,
database layer, session storage mechanism, and even dispatch method are left entirely up to the developer making use
of the framework. Provided are a number of extras requirements, which you can define using a comma-separated list
appended to the package name during installation from the command-line, or within your own package's
install_requires. For example, to install a typical set of development tools at the same time as WebCore, run::
pip install WebCore[development]
The available extras are:
-
development-- this installs a recommended set of development-time packages, includingpytest <http://pytest.org/>__ and a suite of plugins for it, plus thebacklash <https://github.com/TurboGears/backlash>__ interactive debugger (needed by the optionalDebugExtension), object dispatch, the comprehensiveptipythonupgraded REPL, and thewaitress <https://github.com/Pylons/waitress>__ development web server. -
production-- install recommended production-time packages; currently this only installs theflupFastCGI server bridge.
The default choices for dispatch are allowed as extras:
-
object-- install object dispatch -
route-- install route-based dispatch -
traversal-- install traversal dispatch
You can also name a supported server bridge as an extra. Currently available bridges with third-party dependencies include:
-
waitress -
tornado -
flup
Development Version
|developstatus| |developcover| |ghsince| |issuecount| |ghfork|
Development takes place on GitHub <https://github.com/>__ in the
WebCore <https://github.com/marrow/WebCore/>__ project. Issue tracking, documentation, and downloads
are provided there. Development chat (both development of WebCore and chat for users using WebCore to develop their
own solutions) is graciously provided by Freenode <ircs://chat.freenode.net:6697/#webcore>__ in the #webcore
channel.
Installing the current development version requires Git <http://git-scm.com/>__, a distributed source code management
system. If you have Git you can run the following to download and link the development version into your Python
runtime::
git clone https://github.com/marrow/WebCore.git
pip install -e WebCore
You can then upgrade to the latest version at any time::
(cd WebCore; git pull; pip install -e .)
Extra dependenies can be declared the same as per web-based installation::
pip install -e WebCore[development]
If you would like to make changes and contribute them back to the project, fork the GitHub project, make your changes,
and submit a pull request. This process is beyond the scope of this documentation; for more information see
GitHub's documentation <http://help.github.com/>__.
Basic Concepts
Application
The Application class is the primary entry point for the web framework. Its constructor currently takes up to
three arguments:
-
root-- the root object to use as the controller for/requests -
extensions-- a list of extensions to use with your application -
logging-- Pythonloggingconfiguration
The "root controller" is used as the starting point for dispatch resolution of the endpoint for a request, see the Controllers section below for details on what can be used here, but it's basically anything.
By default the BaseExtension, providing basic request and response objects and basic views, is always enabled for
your application, has no configuration, and does not need to be instantiated yourself. Other extensions should be
instantiated and passed in the extensions list.
Logging configuration offers two choices: simple "global logging level" by defining logging as a dictionary
only containing a level key naming the level to set, or full logging.config.dictConfig configuration. Passing
only a level is equivalent to running logging.basicConfig.
This configuration can entirely come from YAML, for example::
root: !!python/name:web.app.example.RootController
extensions:
- !!python/object:web.ext.debug.DebugExtension
- !!python/object:web.ext.analytics.AnalyticsExtension
- !!python/object:web.ext.annotation:AnnotationExtension
logging:
level: debug
This would make managing complex extension configuration easier. One way to invoke WebCore with a configuration like this, while allowing for a distinction between production and development environments and use under ModWSGI would be::
import yaml
from web.core import Application
fname = 'development.yaml' if __debug__ else 'production.yaml'
with open(fname, 'r', encoding='utf-8') as fh:
config = yaml.load(fh)
app = Application(**config)
if __name__ == "__main__":
app.serve('wsgiref')
Now, running python run.py (if saved as run.py) would serve the development.yaml configuration, and
running as python -O run.py (optimization enabled) or with PYTHONOPTIMIZE=1 set in the environment will
utilize the production.yaml file.
WebCore is highly aware running with optimizations enabled, eliminating many of the expensive validation checks that
are only really useful in development. For example, calling an endpoint with invalid arguments will 404 with a
friendly warning in development, but 500 in production as the TypeError is not preemptively checked and
caught; this is one of the most expensive validation checks. Feel free to browse the code looking for if __debug__
blocks to see what else changes in "production mode".
The order you define the extensions in does not matter; they declare dependencies and will be automatically
dependency-ordered when collecting callbacks. Please see the extension.py example for additional information on
what you can do with them.
Context
The overall application has an ApplicationContext associated with it. This object is passed around to the various
extension callbacks and acts as an attribute access dictionary. (All of the typical dictionary methods will work,
and the keys can be accessed as attributes instead, saving some typing.) During the processing of a request a subclass
is constructed called RequestContext and in-request extension callbacks, and your controller endpoints, are given
a reference to this instance.
The attributes present in the base ApplicationContext are:
-
app-- a reference to theApplicationinstance -
root-- the original object passed when constructing theApplicationinstance -
extension-- theWebExtensionsextension registry -
dispatch-- theWebDispatchersdispatch protocol bridge and plugin registry -
view-- theWebViewsview handler registry
Extensions would access these during start and stop events, fo
