Metadata-Version: 2.1
Name: webresource
Version: 1.1
Summary: A resource registry for web applications.
Home-page: UNKNOWN
Author: Conestack Constributors
Author-email: dev@conestack.org
License: Simplified BSD
Project-URL: Documentation, https://webresource.readthedocs.io/
Project-URL: ChangeLog, https://github.com/conestack/webresource/blob/master/CHANGES.rst
Project-URL: Issue Tracker, https://github.com/conestack/webresource/issues
Project-URL: Source Code, https://github.com/conestack/webresource
Keywords: web resources dependencies javascript CSS
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Provides-Extra: docs
Requires-Dist: Sphinx ; extra == 'docs'
Requires-Dist: sphinx-conestack-theme ; extra == 'docs'
Provides-Extra: test
Requires-Dist: coverage ; extra == 'test'

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'
        ...
    )

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.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.


