Metadata-Version: 2.1
Name: xblock-utils
Version: 2.1.3
Summary: Various utilities for XBlocks
Home-page: https://github.com/edx/xblock-utils
Author: edX
Author-email: oscm@edx.org
License: UNKNOWN
Platform: UNKNOWN
Classifier: Framework :: Django :: 2.2
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
License-File: LICENSE

xblock-utils: Various utilities for XBlocks
===========================================

These are a collection of useful utility functions,
test base classes and documentation shared by many XBlocks.
(Especially those of `edx-solutions`_.)

.. _edx-solutions: https://github.com/edx-solutions


To test the utilities, run::

    make test

To get a coverage report, use::

    tox -- --cover-html


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/edx/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/edx/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/edx/xblock-utils/wiki/Settings-and-theme-support#theming-support) for details

