xblock-utils: Various utilities for XBlocks
###########################################
|pypi-badge| |ci-badge| |codecov-badge| |doc-badge| |pyversions-badge|
|license-badge| |status-badge|
Purpose
*******
These are a collection of utility functions, base test classes and
documentation that are useful for any XBlocks.
⚠️ Deprecation Notice ⚠️
************************
**Effective Date:** September 26, 2023
**Repository Migration:**
This `xblock-utils` repository has been `deprecated <https://github.com/openedx/xblock-utils/issues/197>`_ as of September 26, 2023, and the code and documentation have been migrated to the `Xblock <https://github.com/openedx/XBlock>`_ repository.
This decision was made to streamline and consolidate our codebase.
The migration process was completed through this Pull Request: `PR #669 <https://github.com/openedx/XBlock/pull/669>`_
**Archival**: We are going to archive the `xblock-utils` repository. This means that it will become read-only, and no further updates or changes will be accepted.
We appreciate your understanding and cooperation during this transition. If you have any questions or concerns, please don't hesitate to reach out to us through the `XBlock` repository's issue tracker.
Thank you for your continued support and contributions to the Open edX community.
Getting Started
***************
Developing
==========
One Time Setup
--------------
.. code-block::
# Clone the repository
git clone git@github.com:openedx/xblock-utils.git
cd xblock-utils
# Set up a virtualenv with the same name as the repo and activate it
# Here's how you might do that if you have virtualenvwrapper setup.
mkvirtualenv -p python3.8 xblock-utils
Every time you develop something in this repo
---------------------------------------------
.. code-block::
# Activate the virtualenv
# Here's how you might do that if you're using virtualenvwrapper.
workon xblock-utils
# Grab the latest code
git checkout master
git pull
# Install/update the dev requirements
make requirements
# Run the tests and quality checks (to verify the status before you make any changes)
make test
# Make a new branch for your changes
git checkout -b <your_github_username>/<short_description>
# Using your favorite editor, edit the code to make your change.
vim ...
# Temporary until https://github.com/openedx/xblock-utils/issues/199 is resolved
mkdir var
touch var/workbench.log
# Run your new tests
pytest ./path/to/new/tests
# Run all the tests and quality checks
make test
# Commit all your changes
git commit ...
git push
# Open a PR and ask for review.
Deploying
=========
This component is automatically deployed to PyPI whenever new GitHub releases are made.
To deploy this library.
#. Update the version in ``xblockutils/__init__.py`` based on semantic versioning.
#. Create a new GitHub release with a tag matching the version.
#. Automation should build and deploy the version to PyPI
Getting Help
************
Documentation
=============
Start by going through `the documentation`_. If you need more help see below.
.. _the documentation: https://docs.openedx.org/projects/xblock-utils
More Help
=========
If you're having trouble, we have discussion forums at
https://discuss.openedx.org where you can connect with others in the
community.
Our real-time conversations are on Slack. You can request a `Slack
invitation`_, then join our `community Slack workspace`_.
For anything non-trivial, the best path is to open an issue in this
repository with as many details about the issue you are facing as you
can provide.
https://github.com/openedx/xblock-utils/issues
For more information about these options, see the `Project Getting Help`_ page.
.. _Slack invitation: https://openedx.org/slack
.. _community Slack workspace: https://openedx.slack.com/
.. _Project Getting Help: https://openedx.org/getting-help
License
*******
The code in this repository is licensed under the AGPLv3 unless
otherwise noted.
Please see `the LICENSE <LICENSE>`_ for details.
Contributing
************
Contributions are very welcome.
Please read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for details.
This project is currently accepting all types of contributions, bug fixes,
security fixes, maintenance work, or new features. However, please make sure
to have a discussion about your new feature idea with the maintainers prior to
beginning development to maximize the chances of your change being accepted.
You can start a conversation by creating a new issue on this repo summarizing
your idea.
The Open edX Code of Conduct
****************************
All community members are expected to follow the `Open edX Code of Conduct`_.
.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/
People
******
The assigned maintainers for this component and other project details may be
found in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``
file in this repo.
.. _Backstage: https://backstage.openedx.org/catalog/default/component/xblock-utils
Reporting Security Issues
*************************
Please do not report security issues in public. Please email security@openedx.org.
.. |pypi-badge| image:: https://img.shields.io/pypi/v/xblock-utils.svg
:target: https://pypi.python.org/pypi/xblock-utils/
:alt: PyPI
.. |ci-badge| image:: https://github.com/openedx/xblock-utils/workflows/Python%20CI/badge.svg?branch=main
:target: https://github.com/openedx/xblock-utils/actions
:alt: CI
.. |codecov-badge| image:: https://codecov.io/github/openedx/xblock-utils/coverage.svg?branch=main
:target: https://codecov.io/github/openedx/xblock-utils?branch=main
:alt: Codecov
.. |doc-badge| image:: https://readthedocs.org/projects/xblock-utils/badge/?version=latest
:target: https://docs.openedx.org/projects/xblock-utils/
:alt: Documentation
.. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/xblock-utils.svg
:target: https://pypi.python.org/pypi/xblock-utils/
:alt: Supported Python versions
.. |license-badge| image:: https://img.shields.io/github/license/openedx/xblock-utils.svg
:target: https://github.com/openedx/xblock-utils/blob/main/LICENSE
:alt: License
.. |status-badge| image:: https://img.shields.io/badge/Status-Maintained-brightgreen
More Documentation
******************
StudioEditableXBlockMixin
=========================
.. code:: python
from xblockutils.studio_editable import StudioEditableXBlockMixin
This mixin will automatically generate a working ``studio_view`` form
that allows content authors to edit the fields of your XBlock. To use,
simply add the class to your base class list, and add a new class field
called ``editable_fields``, set to a tuple of the names of the fields
you want your user to be able to edit.
.. code:: python
@XBlock.needs("i18n")
class ExampleBlock(StudioEditableXBlockMixin, XBlock):
...
mode = String(
display_name="Mode",
help="Determines the behaviour of this component. Standard is recommended.",
default='standard',
scope=Scope.content,
values=('standard', 'crazy')
)
editable_fields = ('mode', 'display_name')
That's all you need to do. The mixin will read the optional
``display_name``, ``help``, ``default``, and ``values`` settings from
the fields you mention and build the editor form as well as an AJAX save
handler.
If you want to validate the data, you can override
``validate_field_data(self, validation, data)`` and/or
``clean_studio_edits(self, data)`` - see the source code for details.
Supported field types:
* Boolean:
``field_name = Boolean(display_name="Field Name")``
* Float:
``field_name = Float(display_name="Field Name")``
* Integer:
``field_name = Integer(display_name="Field Name")``
* String:
``field_name = String(display_name="Field Name")``
* String (multiline):
``field_name = String(multiline_editor=True, resettable_editor=False)``
* String (html):
``field_name = String(multiline_editor='html', resettable_editor=False)``
Any of the above will use a dropdown menu if they have a pre-defined
list of possible values.
* List of unordered unique values (i.e. sets) drawn from a small set of
possible values:
``field_name = List(list_style='set', list_values_provider=some_method)``
- The ``List`` declaration must include the property ``list_style='set'`` to
indicate that the ``List`` field is being used with set semantics.
- The ``List`` declaration must also define a ``list_values_provider`` method
which will be called with the block as its only parameter and which must
return a list of possible values.
* Rudimentary support for Dict, ordered List, and any other JSONField-derived field types
- ``list_field = List(display_name="Ordered List", default=[])``
- ``dict_field = Dict(display_name="Normal Dict", default={})``
Supported field options (all field types):
* ``values`` can define a list of possible options, changing the UI element
to a select box. Values can be set to any of the formats `defined in the
XBlock source code <https://github.com/openedx/XBlock/blob/master/xblock/fields.py>`__:
- A finite set of elements: ``[1, 2, 3]``
- A finite set of elements where the display names differ from the values::
[
{"display_name": "Always", "value": "always"},
{"display_name": "Past Due", "value": "past_due"},
]
- A range for floating point numbers with specific increments:
``{"min": 0 , "max": 10, "step": .1}``
- A callable that returns one of the above. (Note: the callable does
*not* get passed the XBlock instance or runtime, so it cannot be a
normal member function)
* ``values_provider`` can define a callable that accepts the XBlock
instance as an argument, and returns a list of possible values in one
of the formats listed above.
* ``resettable_editor`` - defaults to ``True``. Set ``False`` to hide the
"Reset" button used to return a field to its default value by removing
the field's value from the XBlock instance.
Basic screenshot: |Screenshot 1|
StudioContainerXBlockMixin
==========================
.. code:: python
from xblockutils.studio_editable import StudioContainerXBlockMixin
This mixin helps to create XBlocks that allow content authors to add,
remove, or reorder child blocks. By removing any existing
``author_view`` and adding this mixin, you'll get editable,
re-orderable, and deletable child support in Studio. To enable authors to
add arbitrary blocks as children, simply override ``author_edit_view``
and set ``can_add=True`` when calling ``render_children`` - see the
source code. To restrict authors so they can add only specific types of
child blocks or a limited number of children requires custom HTML.
An example is the mentoring XBlock: |Screenshot 2|
SeleniumXBlockTest
==================
.. code:: python
from xblockutils.base_test import SeleniumXBlockTest
This is a base class that you can use for writing Selenium integration
tests that are hosted in the XBlock SDK (Workbench).
Here is an example:
.. code:: python
class TestStudentView(SeleniumXBlockTest):
"""
Test the Student View of MyCoolXBlock
"""
def setUp(self):
super(TestStudentView, self).setUp()
self.set_scenario_xml('<mycoolblock display_name="Test Demo Block" field2="hello" />')
self.element = self.go_to_view("student_view")
def test_shows_field_2(self):
"""
The xblock should display the text value of field2.
"""
self.assertIn("hello", self.element.text)
StudioEditableBaseTest
======================
.. code:: python
from xblockutils.studio_editable_test import StudioEditableBaseTest
This is a subclass of ``SeleniumXBlockTest`` that adds a few helper
methods useful for testing the ``studio_view`` of any XBlock using
``StudioEditableXBlockMixin``.
child\_isinstance
=================
.. code:: python
from xblockutils.helpers import child_isinstance
If your XBlock needs to find children/descendants of a particular
class/mixin, you should use
.. code:: python
child_isinstance(self, child_usage_id, SomeXBlockClassOrMixin)
rather than calling
.. code:: python
``isinstance(self.runtime.get_block(child_usage_id), SomeXBlockClassOrMixin)``.
On runtimes such as those in edx-platform, ``child_isinstance`` is
orders of magnitude faster.
.. |Screenshot 1| image:: https://cloud.githubusercontent.com/assets/945577/6341782/7d237966-bb83-11e4-9344-faa647056999.png
.. |Screenshot 2| image:: https://cloud.githubusercontent.com/assets/945577/6341803/d0195ec4-bb83-11e4-82f6-8052c9f70690.png
XBlockWithSettingsMixin
=======================
This mixin provides access to instance-wide XBlock-specific configuration settings.
See [wiki page](https://github.com/openedx/xblock-utils/wiki/Settings-and-theme-support#accessing-xblock-specific-settings) for details
ThemableXBlockMixin
===================
This mixin provides XBlock theming capabilities built on top of XBlock-specific settings.
See [wiki page](https://github.com/openedx/xblock-utils/wiki/Settings-and-theme-support#theming-support) for details
Raw data
{
"_id": null,
"home_page": "https://github.com/openedx/xblock-utils",
"name": "xblock-utils",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "edX",
"author_email": "oscm@edx.org",
"download_url": "https://files.pythonhosted.org/packages/bb/96/032f886808ccc9fe189e16f402193d9e3a03580530e28c7280630fa57a47/xblock-utils-4.0.0.tar.gz",
"platform": null,
"description": "xblock-utils: Various utilities for XBlocks\n###########################################\n\n|pypi-badge| |ci-badge| |codecov-badge| |doc-badge| |pyversions-badge|\n|license-badge| |status-badge|\n\nPurpose\n*******\n\nThese are a collection of utility functions, base test classes and\ndocumentation that are useful for any XBlocks.\n\n\n\u26a0\ufe0f Deprecation Notice \u26a0\ufe0f\n************************\n\n**Effective Date:** September 26, 2023\n\n**Repository Migration:**\nThis `xblock-utils` repository has been `deprecated <https://github.com/openedx/xblock-utils/issues/197>`_ as of September 26, 2023, and the code and documentation have been migrated to the `Xblock <https://github.com/openedx/XBlock>`_ repository.\n\nThis decision was made to streamline and consolidate our codebase.\n\nThe migration process was completed through this Pull Request: `PR #669 <https://github.com/openedx/XBlock/pull/669>`_\n\n**Archival**: We are going to archive the `xblock-utils` repository. This means that it will become read-only, and no further updates or changes will be accepted.\n\nWe appreciate your understanding and cooperation during this transition. If you have any questions or concerns, please don't hesitate to reach out to us through the `XBlock` repository's issue tracker.\n\nThank you for your continued support and contributions to the Open edX community.\n\n\nGetting Started\n***************\n\nDeveloping\n==========\n\nOne Time Setup\n--------------\n.. code-block::\n\n # Clone the repository\n git clone git@github.com:openedx/xblock-utils.git\n cd xblock-utils\n\n # Set up a virtualenv with the same name as the repo and activate it\n # Here's how you might do that if you have virtualenvwrapper setup.\n mkvirtualenv -p python3.8 xblock-utils\n\n\nEvery time you develop something in this repo\n---------------------------------------------\n.. code-block::\n\n # Activate the virtualenv\n # Here's how you might do that if you're using virtualenvwrapper.\n workon xblock-utils\n\n # Grab the latest code\n git checkout master\n git pull\n\n # Install/update the dev requirements\n make requirements\n\n # Run the tests and quality checks (to verify the status before you make any changes)\n make test \n\n # Make a new branch for your changes\n git checkout -b <your_github_username>/<short_description>\n\n # Using your favorite editor, edit the code to make your change.\n vim ...\n\n # Temporary until https://github.com/openedx/xblock-utils/issues/199 is resolved\n mkdir var\n touch var/workbench.log\n\n # Run your new tests\n pytest ./path/to/new/tests\n\n # Run all the tests and quality checks\n make test\n\n # Commit all your changes\n git commit ...\n git push\n\n # Open a PR and ask for review.\n\nDeploying\n=========\n\nThis component is automatically deployed to PyPI whenever new GitHub releases are made.\n\nTo deploy this library.\n\n#. Update the version in ``xblockutils/__init__.py`` based on semantic versioning.\n\n#. Create a new GitHub release with a tag matching the version.\n\n#. Automation should build and deploy the version to PyPI\n\nGetting Help\n************\n\nDocumentation\n=============\n\nStart by going through `the documentation`_. If you need more help see below.\n\n.. _the documentation: https://docs.openedx.org/projects/xblock-utils\n\nMore Help\n=========\n\nIf you're having trouble, we have discussion forums at\nhttps://discuss.openedx.org where you can connect with others in the\ncommunity.\n\nOur real-time conversations are on Slack. You can request a `Slack\ninvitation`_, then join our `community Slack workspace`_.\n\nFor anything non-trivial, the best path is to open an issue in this\nrepository with as many details about the issue you are facing as you\ncan provide.\n\nhttps://github.com/openedx/xblock-utils/issues\n\nFor more information about these options, see the `Project Getting Help`_ page.\n\n.. _Slack invitation: https://openedx.org/slack\n.. _community Slack workspace: https://openedx.slack.com/\n.. _Project Getting Help: https://openedx.org/getting-help\n\nLicense\n*******\n\nThe code in this repository is licensed under the AGPLv3 unless\notherwise noted.\n\nPlease see `the LICENSE <LICENSE>`_ for details.\n\nContributing\n************\n\nContributions are very welcome.\nPlease read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for details.\n\nThis project is currently accepting all types of contributions, bug fixes,\nsecurity fixes, maintenance work, or new features. However, please make sure\nto have a discussion about your new feature idea with the maintainers prior to\nbeginning development to maximize the chances of your change being accepted.\nYou can start a conversation by creating a new issue on this repo summarizing\nyour idea.\n\nThe Open edX Code of Conduct\n****************************\n\nAll community members are expected to follow the `Open edX Code of Conduct`_.\n\n.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/\n\nPeople\n******\n\nThe assigned maintainers for this component and other project details may be\nfound in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``\nfile in this repo.\n\n.. _Backstage: https://backstage.openedx.org/catalog/default/component/xblock-utils\n\nReporting Security Issues\n*************************\n\nPlease do not report security issues in public. Please email security@openedx.org.\n\n.. |pypi-badge| image:: https://img.shields.io/pypi/v/xblock-utils.svg\n :target: https://pypi.python.org/pypi/xblock-utils/\n :alt: PyPI\n\n.. |ci-badge| image:: https://github.com/openedx/xblock-utils/workflows/Python%20CI/badge.svg?branch=main\n :target: https://github.com/openedx/xblock-utils/actions\n :alt: CI\n\n.. |codecov-badge| image:: https://codecov.io/github/openedx/xblock-utils/coverage.svg?branch=main\n :target: https://codecov.io/github/openedx/xblock-utils?branch=main\n :alt: Codecov\n\n.. |doc-badge| image:: https://readthedocs.org/projects/xblock-utils/badge/?version=latest\n :target: https://docs.openedx.org/projects/xblock-utils/\n :alt: Documentation\n\n.. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/xblock-utils.svg\n :target: https://pypi.python.org/pypi/xblock-utils/\n :alt: Supported Python versions\n\n.. |license-badge| image:: https://img.shields.io/github/license/openedx/xblock-utils.svg\n :target: https://github.com/openedx/xblock-utils/blob/main/LICENSE\n :alt: License\n\n.. |status-badge| image:: https://img.shields.io/badge/Status-Maintained-brightgreen\n\nMore Documentation\n******************\n\nStudioEditableXBlockMixin\n=========================\n\n.. code:: python\n\n from xblockutils.studio_editable import StudioEditableXBlockMixin\n\nThis mixin will automatically generate a working ``studio_view`` form\nthat allows content authors to edit the fields of your XBlock. To use,\nsimply add the class to your base class list, and add a new class field\ncalled ``editable_fields``, set to a tuple of the names of the fields\nyou want your user to be able to edit.\n\n.. code:: python\n\n @XBlock.needs(\"i18n\")\n class ExampleBlock(StudioEditableXBlockMixin, XBlock):\n ...\n mode = String(\n display_name=\"Mode\",\n help=\"Determines the behaviour of this component. Standard is recommended.\",\n default='standard',\n scope=Scope.content,\n values=('standard', 'crazy')\n )\n editable_fields = ('mode', 'display_name')\n\nThat's all you need to do. The mixin will read the optional\n``display_name``, ``help``, ``default``, and ``values`` settings from\nthe fields you mention and build the editor form as well as an AJAX save\nhandler.\n\nIf you want to validate the data, you can override\n``validate_field_data(self, validation, data)`` and/or\n``clean_studio_edits(self, data)`` - see the source code for details.\n\nSupported field types:\n\n* Boolean:\n ``field_name = Boolean(display_name=\"Field Name\")``\n* Float:\n ``field_name = Float(display_name=\"Field Name\")`` \n* Integer:\n ``field_name = Integer(display_name=\"Field Name\")`` \n* String:\n ``field_name = String(display_name=\"Field Name\")`` \n* String (multiline):\n ``field_name = String(multiline_editor=True, resettable_editor=False)``\n* String (html):\n ``field_name = String(multiline_editor='html', resettable_editor=False)``\n\nAny of the above will use a dropdown menu if they have a pre-defined\nlist of possible values.\n\n* List of unordered unique values (i.e. sets) drawn from a small set of\n possible values:\n ``field_name = List(list_style='set', list_values_provider=some_method)``\n\n - The ``List`` declaration must include the property ``list_style='set'`` to\n indicate that the ``List`` field is being used with set semantics.\n - The ``List`` declaration must also define a ``list_values_provider`` method\n which will be called with the block as its only parameter and which must\n return a list of possible values.\n* Rudimentary support for Dict, ordered List, and any other JSONField-derived field types\n\n - ``list_field = List(display_name=\"Ordered List\", default=[])``\n - ``dict_field = Dict(display_name=\"Normal Dict\", default={})``\n\nSupported field options (all field types):\n\n* ``values`` can define a list of possible options, changing the UI element\n to a select box. Values can be set to any of the formats `defined in the\n XBlock source code <https://github.com/openedx/XBlock/blob/master/xblock/fields.py>`__:\n\n - A finite set of elements: ``[1, 2, 3]``\n - A finite set of elements where the display names differ from the values::\n\n [\n {\"display_name\": \"Always\", \"value\": \"always\"},\n {\"display_name\": \"Past Due\", \"value\": \"past_due\"},\n ]\n - A range for floating point numbers with specific increments:\n ``{\"min\": 0 , \"max\": 10, \"step\": .1}``\n - A callable that returns one of the above. (Note: the callable does\n *not* get passed the XBlock instance or runtime, so it cannot be a\n normal member function)\n* ``values_provider`` can define a callable that accepts the XBlock\n instance as an argument, and returns a list of possible values in one\n of the formats listed above.\n* ``resettable_editor`` - defaults to ``True``. Set ``False`` to hide the\n \"Reset\" button used to return a field to its default value by removing\n the field's value from the XBlock instance.\n\nBasic screenshot: |Screenshot 1|\n\nStudioContainerXBlockMixin\n==========================\n\n.. code:: python\n\n from xblockutils.studio_editable import StudioContainerXBlockMixin\n\nThis mixin helps to create XBlocks that allow content authors to add,\nremove, or reorder child blocks. By removing any existing\n``author_view`` and adding this mixin, you'll get editable,\nre-orderable, and deletable child support in Studio. To enable authors to\nadd arbitrary blocks as children, simply override ``author_edit_view`` \nand set ``can_add=True`` when calling ``render_children`` - see the \nsource code. To restrict authors so they can add only specific types of\nchild blocks or a limited number of children requires custom HTML.\n\nAn example is the mentoring XBlock: |Screenshot 2|\n\nSeleniumXBlockTest\n==================\n\n.. code:: python\n\n from xblockutils.base_test import SeleniumXBlockTest\n\nThis is a base class that you can use for writing Selenium integration\ntests that are hosted in the XBlock SDK (Workbench).\n\nHere is an example:\n\n.. code:: python\n\n class TestStudentView(SeleniumXBlockTest):\n \"\"\"\n Test the Student View of MyCoolXBlock\n \"\"\"\n def setUp(self):\n super(TestStudentView, self).setUp()\n self.set_scenario_xml('<mycoolblock display_name=\"Test Demo Block\" field2=\"hello\" />')\n self.element = self.go_to_view(\"student_view\")\n\n def test_shows_field_2(self):\n \"\"\"\n The xblock should display the text value of field2.\n \"\"\"\n self.assertIn(\"hello\", self.element.text)\n\nStudioEditableBaseTest\n======================\n\n.. code:: python\n\n from xblockutils.studio_editable_test import StudioEditableBaseTest\n\nThis is a subclass of ``SeleniumXBlockTest`` that adds a few helper\nmethods useful for testing the ``studio_view`` of any XBlock using\n``StudioEditableXBlockMixin``.\n\nchild\\_isinstance\n=================\n\n.. code:: python\n\n from xblockutils.helpers import child_isinstance\n\nIf your XBlock needs to find children/descendants of a particular\nclass/mixin, you should use\n\n.. code:: python\n\n child_isinstance(self, child_usage_id, SomeXBlockClassOrMixin)\n\nrather than calling\n\n.. code:: python\n\n ``isinstance(self.runtime.get_block(child_usage_id), SomeXBlockClassOrMixin)``.\n\nOn runtimes such as those in edx-platform, ``child_isinstance`` is\norders of magnitude faster.\n\n.. |Screenshot 1| image:: https://cloud.githubusercontent.com/assets/945577/6341782/7d237966-bb83-11e4-9344-faa647056999.png\n.. |Screenshot 2| image:: https://cloud.githubusercontent.com/assets/945577/6341803/d0195ec4-bb83-11e4-82f6-8052c9f70690.png\n\nXBlockWithSettingsMixin\n=======================\n\nThis mixin provides access to instance-wide XBlock-specific configuration settings.\nSee [wiki page](https://github.com/openedx/xblock-utils/wiki/Settings-and-theme-support#accessing-xblock-specific-settings) for details\n\nThemableXBlockMixin\n===================\n\nThis mixin provides XBlock theming capabilities built on top of XBlock-specific settings.\nSee [wiki page](https://github.com/openedx/xblock-utils/wiki/Settings-and-theme-support#theming-support) for details\n\n\n",
"bugtrack_url": null,
"license": "",
"summary": "Various utilities for XBlocks",
"version": "4.0.0",
"project_urls": {
"Homepage": "https://github.com/openedx/xblock-utils"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "02af5cea407aeea6d2da117721f1df3c0d124631ed11d437fd066dfe9125fb92",
"md5": "a43bd8b3053408d144d12da58e0b1337",
"sha256": "45c2bb9c4279b1db20353ad03c47315ee849c5a5c806dfc33ec10492cb125a2b"
},
"downloads": -1,
"filename": "xblock_utils-4.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a43bd8b3053408d144d12da58e0b1337",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 31457,
"upload_time": "2023-10-04T05:56:26",
"upload_time_iso_8601": "2023-10-04T05:56:26.459016Z",
"url": "https://files.pythonhosted.org/packages/02/af/5cea407aeea6d2da117721f1df3c0d124631ed11d437fd066dfe9125fb92/xblock_utils-4.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "bb96032f886808ccc9fe189e16f402193d9e3a03580530e28c7280630fa57a47",
"md5": "841d3dbb61f04d66f10acff2280e7763",
"sha256": "a24f0cd87b7f6cc25253390f85c6234c6e27e3cb9d4457ee27289d9a0f3dfb38"
},
"downloads": -1,
"filename": "xblock-utils-4.0.0.tar.gz",
"has_sig": false,
"md5_digest": "841d3dbb61f04d66f10acff2280e7763",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 35575,
"upload_time": "2023-10-04T05:56:28",
"upload_time_iso_8601": "2023-10-04T05:56:28.223305Z",
"url": "https://files.pythonhosted.org/packages/bb/96/032f886808ccc9fe189e16f402193d9e3a03580530e28c7280630fa57a47/xblock-utils-4.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-04 05:56:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "openedx",
"github_project": "xblock-utils",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "xblock-utils"
}