webresource


Namewebresource JSON
Version 1.2 PyPI version JSON
download
home_page
SummaryA resource registry for web applications.
upload_time2022-12-21 09:00:46
maintainer
docs_urlNone
authorConestack Constributors
requires_python
licenseSimplified BSD
keywords web resources dependencies javascript css
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            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"
}
        
Elapsed time: 0.02868s