webresource
===========
.. image:: https://img.shields.io/pypi/v/webresource.svg
:target: https://pypi.python.org/pypi/webresource
:alt: Latest PyPI version
.. image:: https://img.shields.io/pypi/dm/webresource.svg
:target: https://pypi.python.org/pypi/webresource
:alt: Number of PyPI downloads
**A resource registry for web applications.**
Webresource is a compact Python library to declare resources
(primarily Javascript and CSS files) for delivery in your web application.
Features
--------
- Declare web resources via python.
- Manage dependencies between resources.
- Grouping of resources.
- Conditional delivery of resources.
- Development and a production mode.
Detailed Documentation
----------------------
The detailed ``webresource`` documentation is available
`here <https://webresource.readthedocs.io>`_.
Source Code
-----------
The sources are in a GIT DVCS with its main branches at
`github <http://github.com/conestack/webresource>`_.
Copyright
---------
- Copyright (c) 2021-2022 Cone Contributors
Contributors
------------
- Robert Niederreiter (Author)
Overview
========
Declaring resources
-------------------
Webresource provides 3 types of resources. ``ScriptResource`` is used for
registering Javascript, ``StyleResource`` for CSS files and ``LinkResource``
can be used for registering all sorts of resource links.
Declare a script:
.. code-block:: python
import webresource as wr
my_js = wr.ScriptResource(
name='my_js',
directory='/path/to/scripts',
resource='my.js',
compressed='my.min.js',
path='js'
)
``name`` is a unique identifier for the resource. ``directory`` defines the
location in the file system where the resource can be found. ``resource`` is
the default resource file corresponding to this declaration. ``compressed`` is
the minified version of the resource, which gets considered if Webresource
is used in production mode. ``path`` defines the path part of the URL at which
this resource is published.
Dependencies between resources are defined by passing ``depends`` argument,
which can be a single dependency or multiple dependencies as tuple or list:
.. code-block:: python
other_js = wr.ScriptResource(
name='other_js',
depends='my_js',
...
)
It's possible to pass a callback funtion as ``include`` argument. It can be
used to calculate whether a resource should be included or not:
.. code-block:: python
def include_conditional_js():
# Compute whether to include resource here.
return True
conditional_js = wr.ScriptResource(
name='conditional_js',
include=include_conditional_js,
...
)
The ``include`` property can also be set as boolean which might be useful for
excluding some already registered resources:
.. code-block:: python
conditional_js.include = False
Resource URLs can be rendered including a unique key of the resource file.
This is useful in environments with strong caching to make sure changed
resources get reloaded properly. When working with unique resource URLs, the
unique key gets rendered intermediate between path and file name, thus the
integrator needs to implement custom URL rewriting/dispatching/traversal for
correct resource delivery:
.. code-block:: python
cached_js = wr.ScriptResource(
name='cached_js',
unique=True,
unique_prefix='++webresource++',
...
)
If external resources should be declared, pass ``url`` argument. In this case
``path``, ``resource`` and ``compressed`` get ignored:
.. code-block:: python
external_js = wr.ScriptResource(
name='external_js',
url='https://example.org/resource.js'
...
)
It is possible to render additional attributes on resource tags by passing
additional keyword arguments to the constructor. This can be usefule when
working with web compilers like Diazo.
.. code-block:: python
custom_attr_js = wr.ScriptResource(
name='custom_attr_js',
**{'data-bundle': 'bundle-name'}
)
This examples uses ``ScriptResource`` but the above described behavior applies
to all provided Resource types.
Resource groups
---------------
Resources can be grouped by adding them to ``ResourceGroup`` objects:
.. code-block:: python
scripts = wr.ResourceGroup(name='scripts')
Resources can be added to a group at instantiation time if group is known in
advance.
.. code-block:: python
script = wr.ScriptResource(
name='script',
group=scripts
...
)
or an already declared resource can be added to a group:
.. code-block:: python
scripts.add(script)
Groups can be nested:
.. code-block:: python
scripts = wr.ResourceGroup(name='scripts')
base_scripts = wr.ResourceGroup(
name='base_scripts',
group=scripts
)
addon_scripts = wr.ResourceGroup(
name='addon_scripts',
group=scripts
)
A group can define the default ``path`` for its members. It is taken unless
a contained group member defines a path on its own:
.. code-block:: python
scripts = wr.ResourceGroup(name='scripts', path='js')
Same applies for the resource ``directory``. If defined on a resource group,
is taken unless a contained member overrides it.
.. code-block:: python
scripts = wr.ResourceGroup(name='scripts', directory='/path/to/scripts')
To control whether an entire group should be included, define an ``include``
callback funtion or flag.
.. code-block:: python
def include_group():
# Compute whether to include resource group here.
return True
group = wr.ResourceGroup(
name='group',
include=include_group,
...
)
Deliver resources
-----------------
Webresource not provides any mechanism to publish the declared resources.
It's up to the user to make the resources in the defined directories available
to the browser at the defined paths.
But it provides a renderer for the resulting resource HTML tags.
First a ``ResourceResolver`` needs to be created knowing about the resources to
deliver. ``members`` can be an instance or list of resources or resource groups.
The ``ResourceRenderer`` then is used to create the markup.
The ``GracefulResourceRenderer`` creates the markup, but does not fail if one
resource is invalid. It logs an error and places a comment about the failure
instead of a HTML-tag.
A complete example:
.. code-block:: python
import webresource as wr
icon = wr.LinkResource(
name='icon',
resource='icon.png',
rel='icon',
type_='image/png'
)
css = wr.StyleResource(name='css', resource='styles.css')
ext_css = wr.StyleResource(
name='ext_css',
url='https://ext.org/styles.css'
)
script = wr.ScriptResource(
name='script',
resource='script.js',
compressed='script.min.js'
)
resources = wr.ResourceGroup(name='resources', path='res')
resources.add(icon)
resources.add(css)
resources.add(ext_css)
resources.add(script)
resolver = wr.ResourceResolver(resources)
renderer = wr.ResourceRenderer(resolver, base_url='https://tld.org')
rendered = renderer.render()
``rendered`` results in:
.. code-block:: html
<link href="https://tld.org/res/icon.png"
rel="icon" type="image/png" />
<link href="https://tld.org/res/styles.css" media="all"
rel="stylesheet" type="text/css" />
<link href="https://ext.org/styles.css" media="all"
rel="stylesheet" type="text/css" />
<script src="https://tld.org/res/script.min.js"></script>
Debugging
---------
To prevent Webresource generating links to the compressed versions of
declared resources, ``development`` flag of the config singleton needs to be
set:
.. code-block:: python
wr.config.development = True
Changelog
=========
1.2 (2022-12-21)
----------------
- Accept additional keyword arguments in resources. They get rendered as
additional attributes on resource tag.
[rnix, aormazabal]
1.1 (2022-07-01)
----------------
- Remove relative directory resolving.
[rnix]
- Add ``remove`` function to ``ResourceMixin``.
[rnix]
- Add ``copy`` function to ``ResourceMixin``.
[rnix]
- Add ``scripts``, ``styles``, and ``links`` properties to ``ResourceGroup``.
[rnix]
- Introduce ``parent`` attribute on ``ResourceMixin``. Gets set in
``ResourceGroup.add`` method to provide hierarchy information.
[rnix]
- Remove magic path resolving behavior for resources. Path no longer gets
overwritten in resolver. It gets now aquired from parent if not set on
resource or resource group.
[rnix]
- ``LinkResource`` and ``StyleResource`` have common superclass ``LinkMixin``
now. ``StyleResource`` no longer derives from ``LinkResource``. This way,
link and style resources respective subclasses of it can be differentiated
with ``isinstance``.
[rnix]
- Remove ``sizes`` keyword argument from ``StyleResource`` constructor.
[rnix]
- ``ResourceGroup`` can define a directory for contained resources.
[rnix]
- ``Resource.directory`` no longer gets set to package path by default but
remains ``None``.
[rnix]
- Resources can define multiple dependencies.
[rnix]
1.0 (2022-03-24)
----------------
- Add Tox, Github actions and make it run on Windows.
Modernize setup.[py|cfg].
[jensens]
- Added ``GracefulResourceRenderer``.
Fixes #1.
[jensens]
1.0b8 (2021-09-23)
------------------
- Rename ``hash_`` keyword argument of resources to ``unique``.
- Introduce ``unique_prefix`` keyword argument on resources.
- Change behavior of unique URL generation. Unique key now gets rendered
itermediate between URL path and file name. This way we play nice with caching
servers, but this also implies the need of custom URL
dispatching/rewriting/traversal when working with unique resource URLs.
1.0b7 (2021-08-16)
------------------
- Add auto integrity hash calculation on ``ScriptResource``.
- Add ``hash_`` and ``hash_algorithm`` keyword arguments to ``Resource``,
``ScriptResource``, ``LinkResource`` and ``FileResource``.
- Add ``Resource.file_hash`` property.
- Add ``Resource.file_data`` property.
1.0b6 (2021-08-10)
------------------
- Raise explicit ``ResourceError`` instead of generic ``ValueError``.
1.0b5 (2021-08-09)
------------------
- Make ``Resource.directory`` a R/W property.
1.0b4 (2021-08-08)
------------------
- Change ``path`` cascading behavior. Path set on ``ResourceGroup`` always takes
precedence over its members paths.
- ``include`` property of ``Resource`` and ``ResourceGroup`` can be set from
outside.
1.0b3 (2021-08-06)
------------------
- Add remaining missing rst files to release.
1.0b2 (2021-08-06)
------------------
- Add missing ``docs/source/overview.rst`` to release.
1.0b1 (2021-08-06)
------------------
- Initial release.
Raw data
{
"_id": null,
"home_page": "",
"name": "webresource",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "web resources dependencies javascript CSS",
"author": "Conestack Constributors",
"author_email": "dev@conestack.org",
"download_url": "https://files.pythonhosted.org/packages/0d/d3/7ffc8b9bd114ea17162528e75d8e7a9624b928070375b349e68b500aa515/webresource-1.2.tar.gz",
"platform": null,
"description": "webresource\n===========\n\n.. image:: https://img.shields.io/pypi/v/webresource.svg\n :target: https://pypi.python.org/pypi/webresource\n :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/pypi/dm/webresource.svg\n :target: https://pypi.python.org/pypi/webresource\n :alt: Number of PyPI downloads\n\n**A resource registry for web applications.**\n\nWebresource is a compact Python library to declare resources\n(primarily Javascript and CSS files) for delivery in your web application.\n\n\nFeatures\n--------\n\n- Declare web resources via python.\n- Manage dependencies between resources.\n- Grouping of resources.\n- Conditional delivery of resources.\n- Development and a production mode.\n\n\nDetailed Documentation\n----------------------\n\nThe detailed ``webresource`` documentation is available\n`here <https://webresource.readthedocs.io>`_.\n\n\nSource Code\n-----------\n\nThe sources are in a GIT DVCS with its main branches at\n`github <http://github.com/conestack/webresource>`_.\n\n\nCopyright\n---------\n\n- Copyright (c) 2021-2022 Cone Contributors\n\n\nContributors\n------------\n\n- Robert Niederreiter (Author)\n\nOverview\n========\n\nDeclaring resources\n-------------------\n\nWebresource provides 3 types of resources. ``ScriptResource`` is used for\nregistering Javascript, ``StyleResource`` for CSS files and ``LinkResource``\ncan be used for registering all sorts of resource links.\n\nDeclare a script:\n\n.. code-block:: python\n\n import webresource as wr\n\n my_js = wr.ScriptResource(\n name='my_js',\n directory='/path/to/scripts',\n resource='my.js',\n compressed='my.min.js',\n path='js'\n )\n\n``name`` is a unique identifier for the resource. ``directory`` defines the\nlocation in the file system where the resource can be found. ``resource`` is\nthe default resource file corresponding to this declaration. ``compressed`` is\nthe minified version of the resource, which gets considered if Webresource\nis used in production mode. ``path`` defines the path part of the URL at which\nthis resource is published.\n\nDependencies between resources are defined by passing ``depends`` argument,\nwhich can be a single dependency or multiple dependencies as tuple or list:\n\n.. code-block:: python\n\n other_js = wr.ScriptResource(\n name='other_js',\n depends='my_js',\n ...\n )\n\nIt's possible to pass a callback funtion as ``include`` argument. It can be\nused to calculate whether a resource should be included or not:\n\n.. code-block:: python\n\n def include_conditional_js():\n # Compute whether to include resource here.\n return True\n\n conditional_js = wr.ScriptResource(\n name='conditional_js',\n include=include_conditional_js,\n ...\n )\n\nThe ``include`` property can also be set as boolean which might be useful for\nexcluding some already registered resources:\n\n.. code-block:: python\n\n conditional_js.include = False\n\nResource URLs can be rendered including a unique key of the resource file.\nThis is useful in environments with strong caching to make sure changed\nresources get reloaded properly. When working with unique resource URLs, the\nunique key gets rendered intermediate between path and file name, thus the\nintegrator needs to implement custom URL rewriting/dispatching/traversal for\ncorrect resource delivery:\n\n.. code-block:: python\n\n cached_js = wr.ScriptResource(\n name='cached_js',\n unique=True,\n unique_prefix='++webresource++',\n ...\n )\n\nIf external resources should be declared, pass ``url`` argument. In this case\n``path``, ``resource`` and ``compressed`` get ignored:\n\n.. code-block:: python\n\n external_js = wr.ScriptResource(\n name='external_js',\n url='https://example.org/resource.js'\n ...\n )\n\nIt is possible to render additional attributes on resource tags by passing\nadditional keyword arguments to the constructor. This can be usefule when\nworking with web compilers like Diazo.\n\n.. code-block:: python\n\n custom_attr_js = wr.ScriptResource(\n name='custom_attr_js',\n **{'data-bundle': 'bundle-name'}\n )\n\nThis examples uses ``ScriptResource`` but the above described behavior applies\nto all provided Resource types.\n\n\nResource groups\n---------------\n\nResources can be grouped by adding them to ``ResourceGroup`` objects:\n\n.. code-block:: python\n\n scripts = wr.ResourceGroup(name='scripts')\n\nResources can be added to a group at instantiation time if group is known in\nadvance.\n\n.. code-block:: python\n\n script = wr.ScriptResource(\n name='script',\n group=scripts\n ...\n )\n\nor an already declared resource can be added to a group:\n\n.. code-block:: python\n\n scripts.add(script)\n\nGroups can be nested:\n\n.. code-block:: python\n\n scripts = wr.ResourceGroup(name='scripts')\n base_scripts = wr.ResourceGroup(\n name='base_scripts',\n group=scripts\n )\n addon_scripts = wr.ResourceGroup(\n name='addon_scripts',\n group=scripts\n )\n\nA group can define the default ``path`` for its members. It is taken unless\na contained group member defines a path on its own:\n\n.. code-block:: python\n\n scripts = wr.ResourceGroup(name='scripts', path='js')\n\nSame applies for the resource ``directory``. If defined on a resource group,\nis taken unless a contained member overrides it.\n\n.. code-block:: python\n\n scripts = wr.ResourceGroup(name='scripts', directory='/path/to/scripts')\n\nTo control whether an entire group should be included, define an ``include``\ncallback funtion or flag.\n\n.. code-block:: python\n\n def include_group():\n # Compute whether to include resource group here.\n return True\n\n group = wr.ResourceGroup(\n name='group',\n include=include_group,\n ...\n )\n\n\nDeliver resources\n-----------------\n\nWebresource not provides any mechanism to publish the declared resources.\nIt's up to the user to make the resources in the defined directories available\nto the browser at the defined paths.\n\nBut it provides a renderer for the resulting resource HTML tags.\n\nFirst a ``ResourceResolver`` needs to be created knowing about the resources to\ndeliver. ``members`` can be an instance or list of resources or resource groups.\n\nThe ``ResourceRenderer`` then is used to create the markup.\n\nThe ``GracefulResourceRenderer`` creates the markup, but does not fail if one\nresource is invalid. It logs an error and places a comment about the failure\ninstead of a HTML-tag.\n\nA complete example:\n\n.. code-block:: python\n\n import webresource as wr\n\n icon = wr.LinkResource(\n name='icon',\n resource='icon.png',\n rel='icon',\n type_='image/png'\n )\n\n css = wr.StyleResource(name='css', resource='styles.css')\n\n ext_css = wr.StyleResource(\n name='ext_css',\n url='https://ext.org/styles.css'\n )\n\n script = wr.ScriptResource(\n name='script',\n resource='script.js',\n compressed='script.min.js'\n )\n\n resources = wr.ResourceGroup(name='resources', path='res')\n resources.add(icon)\n resources.add(css)\n resources.add(ext_css)\n resources.add(script)\n\n resolver = wr.ResourceResolver(resources)\n renderer = wr.ResourceRenderer(resolver, base_url='https://tld.org')\n\n rendered = renderer.render()\n\n``rendered`` results in:\n\n.. code-block:: html\n\n <link href=\"https://tld.org/res/icon.png\"\n rel=\"icon\" type=\"image/png\" />\n <link href=\"https://tld.org/res/styles.css\" media=\"all\"\n rel=\"stylesheet\" type=\"text/css\" />\n <link href=\"https://ext.org/styles.css\" media=\"all\"\n rel=\"stylesheet\" type=\"text/css\" />\n <script src=\"https://tld.org/res/script.min.js\"></script>\n\n\nDebugging\n---------\n\nTo prevent Webresource generating links to the compressed versions of\ndeclared resources, ``development`` flag of the config singleton needs to be\nset:\n\n.. code-block:: python\n\n wr.config.development = True\n\nChangelog\n=========\n\n1.2 (2022-12-21)\n----------------\n\n- Accept additional keyword arguments in resources. They get rendered as\n additional attributes on resource tag.\n [rnix, aormazabal]\n\n\n1.1 (2022-07-01)\n----------------\n\n- Remove relative directory resolving.\n [rnix]\n\n- Add ``remove`` function to ``ResourceMixin``.\n [rnix]\n\n- Add ``copy`` function to ``ResourceMixin``.\n [rnix]\n\n- Add ``scripts``, ``styles``, and ``links`` properties to ``ResourceGroup``.\n [rnix]\n\n- Introduce ``parent`` attribute on ``ResourceMixin``. Gets set in\n ``ResourceGroup.add`` method to provide hierarchy information.\n [rnix]\n\n- Remove magic path resolving behavior for resources. Path no longer gets\n overwritten in resolver. It gets now aquired from parent if not set on\n resource or resource group.\n [rnix]\n\n- ``LinkResource`` and ``StyleResource`` have common superclass ``LinkMixin``\n now. ``StyleResource`` no longer derives from ``LinkResource``. This way,\n link and style resources respective subclasses of it can be differentiated\n with ``isinstance``.\n [rnix]\n\n- Remove ``sizes`` keyword argument from ``StyleResource`` constructor.\n [rnix]\n\n- ``ResourceGroup`` can define a directory for contained resources.\n [rnix]\n\n- ``Resource.directory`` no longer gets set to package path by default but\n remains ``None``.\n [rnix]\n\n- Resources can define multiple dependencies.\n [rnix]\n\n\n1.0 (2022-03-24)\n----------------\n\n- Add Tox, Github actions and make it run on Windows.\n Modernize setup.[py|cfg].\n [jensens]\n\n- Added ``GracefulResourceRenderer``. \n Fixes #1.\n [jensens]\n\n\n1.0b8 (2021-09-23)\n------------------\n\n- Rename ``hash_`` keyword argument of resources to ``unique``.\n\n- Introduce ``unique_prefix`` keyword argument on resources.\n\n- Change behavior of unique URL generation. Unique key now gets rendered\n itermediate between URL path and file name. This way we play nice with caching\n servers, but this also implies the need of custom URL\n dispatching/rewriting/traversal when working with unique resource URLs.\n\n\n1.0b7 (2021-08-16)\n------------------\n\n- Add auto integrity hash calculation on ``ScriptResource``.\n\n- Add ``hash_`` and ``hash_algorithm`` keyword arguments to ``Resource``,\n ``ScriptResource``, ``LinkResource`` and ``FileResource``.\n\n- Add ``Resource.file_hash`` property.\n\n- Add ``Resource.file_data`` property.\n\n\n1.0b6 (2021-08-10)\n------------------\n\n- Raise explicit ``ResourceError`` instead of generic ``ValueError``.\n\n\n1.0b5 (2021-08-09)\n------------------\n\n- Make ``Resource.directory`` a R/W property.\n\n\n1.0b4 (2021-08-08)\n------------------\n\n- Change ``path`` cascading behavior. Path set on ``ResourceGroup`` always takes\n precedence over its members paths.\n\n- ``include`` property of ``Resource`` and ``ResourceGroup`` can be set from\n outside.\n\n\n1.0b3 (2021-08-06)\n------------------\n\n- Add remaining missing rst files to release.\n\n\n1.0b2 (2021-08-06)\n------------------\n\n- Add missing ``docs/source/overview.rst`` to release.\n\n\n1.0b1 (2021-08-06)\n------------------\n\n- Initial release.\n\n\n",
"bugtrack_url": null,
"license": "Simplified BSD",
"summary": "A resource registry for web applications.",
"version": "1.2",
"split_keywords": [
"web",
"resources",
"dependencies",
"javascript",
"css"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "db92ae472406489d103416e4a4d1cabf",
"sha256": "448ed3dbff81a7ef8b8ade827a33984520dfe65727e508b3f8ce269db98f8b06"
},
"downloads": -1,
"filename": "webresource-1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "db92ae472406489d103416e4a4d1cabf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 14732,
"upload_time": "2022-12-21T09:00:44",
"upload_time_iso_8601": "2022-12-21T09:00:44.199714Z",
"url": "https://files.pythonhosted.org/packages/95/16/221f117174955e12995270ca64df1a5e29630ae2e6d4e52e363b29532963/webresource-1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "908293dfc31c6e06d16cbca1c90b0305",
"sha256": "361ef36b25b85876a389b755bb4a0d162493b3b0dd3e1f8949284a6fe0341266"
},
"downloads": -1,
"filename": "webresource-1.2.tar.gz",
"has_sig": false,
"md5_digest": "908293dfc31c6e06d16cbca1c90b0305",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 19817,
"upload_time": "2022-12-21T09:00:46",
"upload_time_iso_8601": "2022-12-21T09:00:46.478447Z",
"url": "https://files.pythonhosted.org/packages/0d/d3/7ffc8b9bd114ea17162528e75d8e7a9624b928070375b349e68b500aa515/webresource-1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-21 09:00:46",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "webresource"
}