{ "info": { "author": "4teamwork AG", "author_email": "mailto:info@4teamwork.ch", "bugtrack_url": null, "classifiers": [ "Framework :: Plone", "Framework :: Plone :: 4.3", "Framework :: Plone :: 5.1", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "ftw.lawgiver\n============\n\n``ftw.lawgiver`` generates Plone workflows based on a human readable\nspecification written in a custom\n`DSL `_.\n\n.. contents:: Table of Contents\n\n\nMotivation\n----------\n\nDeveloping and maintaining complex Plone workflows is a time-consuming and\ncumbersome endeavor. Dozens of permissions need to be managed for different\nroles and different workflow states. Usually, this has to be done directly in\nthe ZMI of Zope by selecting or unselecting thousands of checkboxes. This\nprocess has been shown to be very tedious and prone to errors. Furthermore, it\nis no simple task to document the workflow and the associated design decisions\nwhich led to the resulting configuration of permissions and roles. The extension\nor adaption of an existing workflow becomes very difficult, leading to workflows\nwhich are barely maintainable.\n\nAnother problem is the communication between workflow integrator and\ncustomer. The security system of Zope is based on a role-based access control\n(RBAC) which is intrinsically complex due to its use of roles, permissions, and\nworkflow states. Experience has shown that these security concepts can be hard\nto convey to customers.\n\n\nHow it works\n------------\n\n``ftw.lawgiver`` helps solving these problems by using a DSL to describe how\na workflow should work. The lawgiver then generates the complete workflow\ndefinition (``definition.xml``) based on this specification. By separating this\nspecification from the resulting workflow definition (which is in XML) the\nspecification does not have to use permissions--handling the permissions is the\njob of the lawgiver.\n\nUsing the specification file the workflow can easily be regenerated at any time\nand will handle additional permissions automatically when regenerated. However,\nit is still the developer's task to regenerate the ``definition.xml`` whenever\nmore or other permissions have to be managed. He or she has to make sure that\nthe workflow is properly installed with an upgrade step / reindexing security.\n\n\nInstallation\n------------\n\n- Add ``ftw.lawgiver`` to your buildout configuration:\n\n.. code:: rst\n\n [instance]\n eggs +=\n ftw.lawgiver\n\n- Install the generic setup profile of ``ftw.lawgiver``.\n\n\nCompatibility\n-------------\n\nPlone 4.3\n\n\nAction groups\n-------------\n\nIn the specification we use the concept of so called action groups for\ndescribing what a role is allowed to do. It basically groups together a bunch of\nsemantically similar Plone / Zope permissions so that we only have to define the\nworkflow based on these action groups and not on individual permissions.\n\nFor example there is a ``view`` action group which contains permissions such\nas ``View`` and ``Access Contents Information``.\n\n\nRegistering permissions to an action group\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe registration of a permission to an action group should be done in the\npackage where the permission is defined. This allows to keep changes of the\npermissions and action group registrations together in branches, for reviews\netc. ``ftw.lawgiver`` already assigns default Plone / Zope permissions to action\ngroups.\n\nThe registration is done in ZCML.\nHere is an example ``lawgiver.zcml``:\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\nIf you define multiple permissions in the same `map_permissions` directive\nmake sure to separate them by comma.\n\nBy putting the ZCML in a separate ``lawgiver.zcml`` file you can define\nlawgiver in your addon package without having to define a dependency on\n``ftw.lawgiver`` by using ``zcml:condition`` while loading it in your default\n``configure.zcml``:\n\n.. code:: xml\n\n \n\n \n\n \n\n\nOverriding action groups\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nMaybe the permission to action group mapping does not work well for a specific\nworkflow and you would like to change to mapping for this workflow only.\n\nThis can be easily achieved by also defining the workflow in the ZCML:\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\n\nAssigning permission to multiple action groups\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSometimes, a permission should be assigned to multiple action groups.\nThis can be done with the ``move`` attribute of the ``map_permissions`` directive.\nJust make sure that all other ``map_permissions`` ZCMLs are loaded before doing that,\nespecially the default ``lawgiver.zcml`` of ``ftw.lawgiver``.\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n\nWorkflow scope\n~~~~~~~~~~~~~~\n\nThe ``lawgiver:workflow`` directive can be used to group multiple statements and\napply them to a specific workflow.\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n\n\n\nThe workflow specification\n--------------------------\n\nThe specification is written in a plain text file (``specification.txt``) in\nthe same directory where the ``definition.xml`` is saved.\n\n**Examples:**\n\n- `specification.txt (English) `_\n- `specification.de.txt (German) `_\n\n\nStates and transitions\n~~~~~~~~~~~~~~~~~~~~~~\n\nThe states and transitions are defined in simple lists:\n\n.. code:: rst\n\n [My Custom Workflow]\n Description: A three state publication workflow\n Initial Status: Private\n\n Status Private:\n\n Status Pending:\n\n Status Published:\n\n Transitions:\n Publish (Private => Published)\n Submit for publication (Private => Pending)\n Reject (Pending => Private)\n Retract (Pending => Private)\n Publish (Pending => Published)\n Reject (Published => Private)\n\nWe are not using any internal ids for workflow states or\ntransitions. Instead, we use the same labels which the user will actually\nsee--the ids are automatically generated by ``ftw.lawgiver``.\n\n\nRole mapping\n~~~~~~~~~~~~\n\nIn Plone we have a given set of rather technical roles (e.g. Editor,\nContributor, Reader) which may not apply for all use cases in real life. The\ncustomer may have own roles with different names. Since the existing roles are\nalready well established in Plone it is usually not a good thing to add new\nroles to Plone. It is better to try to reuse the existing roles.\n\nBecause the customer has different labels for his roles we need to map\ncustomer roles to Plone roles:\n\n.. code:: rst\n\n Role mapping:\n editor-in-chief => Reviewer\n editor => Editor\n everyone => Anonymous\n\nIn our example we have only \"normal\" editors and an \"editor-in-chief\" who can\nreview and publish the contents. We do not have to use the Contributor role\nsince our editors can edit, add new content, and request a review for existing\ncontent. Therefore, it is not necessary to distinguish Editor and Contributor\nrole.\n\nTransition-guard expressions\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTransition-guard expressions is a way to hide your transitions dynamically,\nin addition to the guard-roles. Use the options-syntax to define a guard-expression.\n\nExpressions in DCWorkflow are TALES expressions. To see the contexts available\nin expressions, take a look at `portal_workflow/[your-workflow-id]/guardExprDocs`\n\nWarning: Transition-guard expressions do not protect the transition itself.\nIf the user knows the URL to perform the transition, it will pass.\nIt only hides the transition from the user.\n\n.. code:: rst\n\n [My Custom Workflow]\n Initial Status: Private\n\n Status Private:\n Status Published:\n\n Transitions:\n Publish (Private => Published) [guard-expression => python:here.guard(state_change)]\n Reject (Published => Private) [guard-expression => here/guard_reject]\n\nGeneral statements\n~~~~~~~~~~~~~~~~~~\n\nUsually there are some general statements, for example that a user with the\nAdminstrator role can always edit the contents in any workflow state. Such\nstatements should not be repeated for every state but defined once as a general\nstatement.\n\nAn example:\n\n.. code:: rst\n\n General:\n An administrator can always view the content\n An administrator can always edit the content\n An administrator can always delete the content\n\nThese general statements apply for all states.\n\n\nDescribing states\n~~~~~~~~~~~~~~~~~\n\nFor each state we describe the actions a user with a certain role can perform.\nWe follow the principle that any user / role is NOT allowed do anything by\ndefault, we have to explicitly list every action he will be allowed to perform.\n\n.. code:: rst\n\n Status Private:\n An editor can view this content.\n An editor can edit this content.\n An editor can delete this content.\n An editor can add new content.\n An editor can submit for publication.\n An editor-in-chief can view this content.\n An editor-in-chief can edit this content.\n An editor-in-chief can delete this content.\n An editor-in-chief can add new content.\n An editor-in-chief can publish this content.\n\n Status Pending:\n An editor can view this content.\n An editor can add new content.\n An editor can retract this content.\n An editor-in-chief can view this content.\n An editor-in-chief can edit this content.\n An editor-in-chief can delete this content.\n An editor-in-chief can add new content.\n An editor-in-chief can publish this content.\n An editor-in-chief can reject this content.\n\n Status Published:\n An editor can view this content.\n An editor can add new content.\n An editor can retract this content.\n An editor-in-chief can view this content.\n An editor-in-chief can add new content.\n An editor-in-chief can retract this content.\n Anyone can view this content.\n\n\nRole inheritance\n~~~~~~~~~~~~~~~~\n\nRoles can be inherited from other roles, globally and for a single status:\n\n.. code:: rst\n\n [Role Inheritance Workflow]\n Initial Status: Foo\n\n Role mapping:\n editor => Editor\n editor-in-chief => Reviewer\n administrator => Site Administrator\n\n General:\n An administrator can always perform the same actions as an editor.\n An administrator can always perform the same actions as an editor-in-chief.\n\n Status Foo:\n An editor-in-chief can perform the same actions as an editor.\n An editor can view this content.\n An editor can edit this content.\n\n Status Bar:\n An editor can view this content.\n An editor-in-chief can view this content.\n An editor-in-chief can edit this content.\n\n\nWorklists\n~~~~~~~~~\n\nWorklists are automatically generated for you when you grant access to the\nworklist:\n\n.. code:: rst\n\n [A workflow]\n ...\n\n Status Pending:\n An editor-in-chief can access the worklist.\n\nThose \"can access the worklist\" statements do not work in the \"General\" section,\nthey need to be defined a \"Status\" section.\n\nFor each status with \"can access the worklist\" statements a worklist is\ngenerated, guarded with the role for which there is a statement.\n\n\nWorkflow specification discovery\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAll workflow directories in registered generic setup profiles\nare automatically scanned for workflow specifications.\nJust place a ``specification.txt`` in a workflow directory and ``ftw.lawgiver``\nwill discover it automatically.\n\nExample paths:\n\n- Specification: ``profiles/default/workflows/my_custom_workflow/specification.txt``\n- Workflow XML: ``profiles/default/workflows/my_custom_workflow/definition.txt``\n\nIn this example it is assumed that ``profiles/default`` is a registered generic setup\nprofile directory.\n\n\nChanging Transition URLs\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nSometimes the transition URLs need to point to another view. This can be\nachieved by using the ``transition-url`` option, where a string can be passed\nwhich will then be substituted with the ``transition`` id. Be sure to use a\ndouble ``%%`` for parts which should not be replaced when generating the workflow,\nsuch as the ``%%(content_url)s``.\n\nExample:\n\n.. code:: rst\n\n transition-url = %%(content_url)s/custom_wf_action?workflow_action=%(transition)s\n\n\nLanguages\n~~~~~~~~~\n\nCurrently supported languages:\n\n**English** (default)\n\n- Filename: ``specification.txt``\n- Example: `ftw/lawgiver/tests/assets/languages/specification.txt `_\n\n**German**\n\n- Filename: ``specification.de.txt``\n- Example: `ftw/lawgiver/tests/assets/languages/specification.de.txt `_\n\n\n**Contributing new languages**\n\nWe happily accept pull requests with new languages!\n\nCreating a new language is as simple:\n\n- Create a new specification example in ``ftw/lawgiver/tests/assets/languages/``,\n implementing the same workflow as ``specification.txt``.\n- Run the tests with ``bin/test``. It should fail at this point. Keep running them\n after each change.\n- Add a new language module to ``ftw/lawgiver/wdl/languages/``.\n- Register the new language in ``ftw/lawgiver/wdl/languages/__init__.py``.\n- Implement the language specific constraints and extraction methods in your new\n language class until all tests pass.\n- Add the language to the readme.\n- Send us a pull request!\n\n\nGenerating the workflow\n-----------------------\n\nFor generating the workflow go to the lawgiver control panel (in the Plone\ncontrol panel). There you can see a list of all workflows and by selecting one\nyou can see the specification and other details, such as the action groups.\n\nOn this view you can generate the workflow (automatically saved to the\n``definition.xml`` in the same directory as the ``specification.txt``) and you\ncan install the workflow / update the security.\n\n.. image:: https://raw.github.com/4teamwork/ftw.lawgiver/master/docs/screenshot-workflow-details.png\n\n\nUpdating translations\n~~~~~~~~~~~~~~~~~~~~~\n\nThe button ``Update translations in locales directory`` in the workflow\ndetails view helps you keep your translations up to date.\nIt writes directly to the locales directory on your machine.\n\nWhen updating the translations, these files are written:\n\n- ``your/package/locales/plone.pot``\n- ``your/package/locales/en/LC_MESSAGES/plone.po``\n\nWhen updating the messages in your locales file, all no longer valid messages\nwhich start with the workflow ID prefix are removed automatically.\n\n\nTesting the workflow\n--------------------\n\nIt is important to detect when you have to rebuild your workflow.\nIt is also important to detect permissions from third party addons which\nare not yet mapped to action groups.\n\nBy subclassing the `WorkflowTest` it is easy to write a test for your\nworkflow:\n\n.. code:: python\n\n from ftw.lawgiver.tests.base import WorkflowTest\n from my.package.testing import MY_INTEGRATION_TESTING\n\n\n class TestMyWorkflow(WorkflowTest):\n\n # The workflow path may be a path relative to the this file or\n # an absolute path.\n workflow_path = '../profiles/default/workflows/my-workflow'\n\n # Use an integration testing layer.\n layer = MY_INTEGRATION_TESTING\n\nWhat is tested?\n\n- The test will fail when your workflow (``definition.xml``) needs to be\n regenerated. This may be because new permissions should be managed.\n\n- The test will fail when you install new addons which provide new\n permissions. The permissions should be mapped to action groups or marked\n as unmanaged explicitly:\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\n\nCustomizing the sharing view\n----------------------------\n\nLawgiver allows you to customize the sharing view to your needs.\n\n\nRoles in sharing view\n~~~~~~~~~~~~~~~~~~~~~\n\nBy default the ``@@sharing`` view lists some default Plone roles:\n\n- Can add (``Contributor``)\n- Can edit (``Editor``)\n- Can review (``Reviewer``)\n- Can view (``Reader``)\n\nOften the workflow does not use all of those roles, or uses different ones.\nLawgiver allows you to configure which roles are showing up in at the ``sharing``\nview. If your users are granting roles on the ``@@sharing`` view, you should probably\nconfigure the roles so that they have meanigful names and only the relevant ones\nare listed.\n\nIf you want to customize the displayed roles for your workflow, you\ncan do this right in your workflow specification:\n\n.. code:: rst\n\n [A workflow]\n\n Role mapping:\n editor => Editor\n editor-in-chief => Reviewer\n administrator => Site Administrator\n\n Visible roles:\n editor\n editor-in-chief\n\nThe lawgiver then sets the permissions required for managing a role correctly.\nThis works for registered roles. Plone only registers ``Contributor``, ``Editor``,\n``Reviewer`` and ``Reader`` by default.\nSee the `Registering additional roles`_ section.\n\n\nTranslating the roles\n~~~~~~~~~~~~~~~~~~~~~\n\nThe lawgiver extends Plone's role translation system so that the\nroles in the ``@@sharing`` view can be translated per workflow.\n\nThis is done through the Plone standard role utilites, allowing addon\ntools to also use the corrent role translation without the need of\ncustomization.\n\nThe lawgiver provides example translations (``plone.pot`` / ``plone.po``) in\nthe lawgiver control panel, which can easily be copied to your local plone\ntranslations (``locales``). These translations also include role translations\nand can be modified to your needs.\n\nThe lawgiver automatically looks up the right translation of the roles, depending\non your workflow.\n\n\nRegistering additional roles\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can easily register custom roles or Plone default roles which are not visible\nby default (such as ``Site Manager``).\n\nUse the lawgiver directive for registering new roles:\n\n.. code:: xml\n\n \n\n \n\n \n\n \n\nThe ``lawgiver:role`` directive does all the required things for you, such as\nregistering the permission in zope, mapping the permission to the default\nlawgiver ``manage security`` action group and registering the required utility\nand adapter.\n\nOptional arguments:\n\n- ``permission``: the required permission for granting this role. The permission\n is automatically generated as ``Sharing page: Delegate [ROLE] role``.\n\n- ``register_permission``: automatically registers the permissions in Zope. This\n is ``True`` by default.\n\n- ``map_permission``: automatically map the permission to the default lawgiver\n ``manage security`` action group. Lawgiver will also re-map the permission\n according to your ``Visible roles`` configuration in the workflow specification.\n\n\nDescription of roles in sharing view\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``ftw.lawgiver`` automatically registers an overlay when clicking on the\nrole text in the table header on the sharing view.\nThe overlay displays a description of what this role can do in each state of\nthe current workflow:\n\n\n.. image:: https://raw.github.com/4teamwork/ftw.lawgiver/master/docs/screenshot-sharing-overlay.png\n\n\nAdding text to the overlay\n++++++++++++++++++++++++++\n\nYou can add text to the overlay per role directly in your workflow specification:\n\n\n.. code:: rst\n\n [A workflow]\n\n Role mapping:\n editor => Editor\n editor-in-chief => Reviewer\n administrator => Site Administrator\n\n editor-in-chief role description:\n The editor-in-chief reviews and publishes content.\n\nThis text is included as translation proposal for the ``plone`` domain, which\nmakes it easy to translate it to other languages for multilingual sites.\n\n\nIntercept and customize transitions\n-----------------------------------\n\nSometimes we need to change the behavior when executing certain transitions.\n``ftw.lawgiver`` provides a base view class ``ModifyStatusViewBase`` for making\nsuch enhancements easier, combined with the ``transition-url`` option in the\nspecification.\n\nThe idea is that a custom view is implemented, subclassing ``ModifyStatusViewBase``.\nThe view can be implemented for one workflow or for multiple workflows in the same project.\nThe view allows to easily intercept certain transitions, changing, enhancing or aborting\nthe standard behavior.\n\nExample\n~~~~~~~\n\n1. Implement a custom view with custom behavior:\n\n .. code:: python\n\n from ftw.lawgiver.browser.modifystatus import ModifyStatusViewBase\n\n class WebModifyStatus(ModifyStatusViewBase):\n\n @ModifyStatusViewBase.intercept('web--TRANSITION--publish--draft-published')\n def verify_on_publish(self, context, transition):\n # verify things\n return self.redirect_to_content_status_modify(context, transition)\n\n The default behavior for not intercepted transitions is to redirect to the default\n ``content_status_modify`` script, which is the default behavior of Plone.\n The default behavior is implemented with the ``redirect_to_content_status_modify``,\n so the example above also falls back to the default behavior.\n\n The base class provides functionality as methods:\n\n - ``execute_transition(context, transition, **kwargs)``: executes the\n ``content_status_modify`` script in-line, so that we can later change the redirect\n or do more things in the same transaction.\n - ``redirect_to_content_status_modify(context, transaction)``: redirects the browser\n the the ``content_status_modify`` script. The script is not executed in the same\n transaction.\n - ``set_workflow_state(context, review_state, **infos)``: changes the workflow state\n of the context without executing a transition or respecting any guards.\n - ``in_state(context, review_state)``: context manager for temporarily\n switching the review state.\n - ``redirect_to(context)``: redirects to the absolute url of the context.\n\n\n2. Register the view in ZCML:\n\n .. code:: xml\n\n \n\n\n3. Configure the lawgiver workflow to use the this view as action:\n\n .. code:: ini\n\n # Settings\n transition-url = %%(content_url)s/@@web-modify-status?transition=%(transition)s\n\n\nSpecialities\n------------\n\nDeleting content with ``collective.deletepermission``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n`collective.deletepermission`_ solves a delete problem, which occurs in certain\nsituations, by adding a new delete permission. See its readme for further\ndetails.\n\nFor being able to delete content, the user should have the ``delete`` action\ngroup (``Delete portal content``) on the content but also ``add`` (``Delete objects``)\non the parent content.\n\n``ftw.lawgiver`` works well with `collective.deletepermission`_.\nUse the extras ``ftw.lawgiver [deletepermission]`` in order to install the\nlawgiver with `collective.deletepermission`_.\n\nBe aware that when you generate your workflows with `collective.deletepermission`_\ninstalled, you need to install `collective.deletepermission`_ in production too.\n\n\nUninstall\n---------\n\nThis package provides an uninstall Generic Setup profile, however, it will\nnot uninstall the package dependencies.\nMake sure to uninstall the dependencies if you no longer use them.\n\n\nRebuild with console\n--------------------\n\n``ftw.lawgiver`` registers a zopectl command so that all workflows can be\nrebuilt at once using the console::\n\n $ ./bin/instance rebuild_workflows --help\n usage: interpreter [-h] [-s SITE]\n\n Rebuild ftw.lawgiver workflows.\n\n optional arguments:\n -h, --help show this help message and exit\n -s SITE, --site SITE Path to the Plone site for discovering the worklfows.\n (default: Plone)\n\n\nLinks\n-----\n\n- Github: https://github.com/4teamwork/ftw.lawgiver\n- Issues: https://github.com/4teamwork/ftw.lawgiver/issues\n- Pypi: http://pypi.python.org/pypi/ftw.lawgiver\n- Continuous integration: https://jenkins.4teamwork.ch/search?q=ftw.lawgiver\n\n\nCopyright\n---------\n\nThis package is copyright by `4teamwork `_.\n\n``ftw.lawgiver`` is licensed under GNU General Public License, version 2.\n\n.. _collective.deletepermission: https://github.com/4teamwork/collective.deletepermission\n.. _ftw.recipe.translations: https://github.com/4teamwork/ftw.recipe.translations\n\nChangelog\n=========\n\n\n1.16.1 (2019-09-12)\n-------------------\n\n- Disable Diazo on lawgiver-sharing-describe-role for Plone 5.1.5 support. [jone]\n- Fix workflow security and brain not updated when setting workflow state on object [Nachtalb]\n\n\n1.16.0 (2018-08-07)\n-------------------\n\n- Support workflow transition guard-expressions. [elioschmutz]\n\n\n1.15.0 (2018-08-03)\n-------------------\n\n- Provide a base class for implementing a custom modify status view. [jone]\n\n1.14.1 (2018-01-15)\n-------------------\n\n- Fix translation domains in ZCML files. [jone]\n- Fix encoding problem when describing roles with non-ASCII characters titles. [jone]\n\n1.14.0 (2018-01-08)\n-------------------\n\n- Drop support for Plone 4.2. [mbaechtold]\n\n- Add support for Plone 5.1. [mbaechtold]\n\n\n1.13.0 (2017-12-18)\n-------------------\n\n- Add new lawgiver:workflow directive. [jone]\n\n\n1.12.0 (2017-12-15)\n-------------------\n\n- Ignore plone.restapi permissions because they are managed globally. [elioschmutz]\n\n\n1.11.0 (2017-12-06)\n-------------------\n\n- Also translate states and transitions with their IDs. [jone]\n- Control panel: separate unmapped permissions into ignored and unknown groups. [jone]\n\n1.10.1 (2017-07-27)\n-------------------\n\n- Fix review state translation in sharing page role description popup.\n The review state is now translated by the state title, not the id. [jone]\n\n1.10.0 (2017-07-11)\n-------------------\n\n- Make ``collective.deletepermission`` dependency optional.\n If you upgrade to this version of ``ftw.lawgiver`` you most likely\n want to enable the ``ftw.lawgiver [deletepermission]`` extra. [jone]\n\n\n1.9.1 (2017-07-10)\n------------------\n\n- Fix typos in German translation [raphael-s]\n\n\n1.9.0 (2017-01-03)\n------------------\n\n- Added control panel button for rebuilding specifications and creating an upgrade step. [jone]\n\n\n1.8.0 (2016-06-30)\n------------------\n\n- Add plone.app.contenttypes permissions to lawgiver.zcml.\n Since plone.app.contenttypes is standard Plone we add the\n plone.app.contenttypes mapping to the lawgiver.zcml.\n [elioschmutz]\n\n\n1.7.0 (2016-05-02)\n------------------\n\n- Add manage translations permissions for plone.app.locales support.\n [raphael-s]\n\n- Ignore the permissions to access inactive and future content because the\n portal catalog checks the Plone root for these permissions, not the context.\n [mbaechtold]\n\n- No longer ignore the permissions to add collection portlet and static\n portlet but rather map them to the existing \"manage portlets\" action group.\n [mbaechtold]\n\n\n1.6.2 (2015-11-16)\n------------------\n\n- Fix UnicodeDecodeError.\n [mbaechtold]\n\n\n1.6.1 (2015-10-08)\n------------------\n\n- Fix translation issues by translationg label instead of ids of\n states and transitions.\n Please rebuild translations for your existing workflows.\n [jone]\n\n\n1.6.0 (2015-05-21)\n------------------\n\n- Add support for assigning permissions to multiple action groups.\n This is done using the ``move=\"False\"`` in ``map_permissions``.\n [jone]\n\n\n1.5.0 (2014-12-08)\n------------------\n\n- Plone 4.3.4: map \"Edit comments\" permission to \"edit\" action group.\n [jone]\n\n\n1.4.0 (2014-09-09)\n------------------\n\n- Implement bin/instance rebuild_workflows command.\n [jone]\n\n- Add button for rebuilding all workflow specifications at once.\n [jone]\n\n- Show a warning on workflows of released eggs.\n [jone]\n\n- i18n generator: escape quotes in generated message strings.\n [jone]\n\n\n1.3.1 (2014-05-28)\n------------------\n\n- Extract `generate_role_translation_id` and `translate_role_for_workflow`\n into utils.\n [jone]\n\n- Fix definition.xml pretty printing on OSX Mavericks.\n On Mavericks most of the definition.xml was written onto a single line.\n [jone]\n\n\n1.3.0 (2014-05-19)\n------------------\n\n- Add role description statements for describing roles.\n This allows to add a text description per role, which will\n be displayed in the new role description overlay in the sharing\n view.\n [jone]\n\n- Fix bug with default permission of \"role\" directive.\n The default permission used to not be set correctly.\n [jone]\n\n- Implement uninstall profile.\n [jone]\n\n- Workflow details: new button for updating the translations in\n the locales directory of your package.\n [jone]\n\n- Implement overlay in sharing view, describing the actions and transitions\n for a role.\n [jone]\n\n- Add German specification support.\n [jone]\n\n- Add support for non-English specifications parsing.\n [jone]\n\n\n1.2.2 (2014-01-09)\n------------------\n\n- Fix wrong role title when traversing over views.\n [jone]\n\n- Fix local roles adapter lookup when no traversal happened beforehand.\n This is a rare issue occured because of the context guessing happing\n in the dynamic role adapter lookup (DynamicRolesUtility.get_role_adapter).\n [jone]\n\n\n1.2.1 (2013-11-26)\n------------------\n\n- Map plone.app.event's \"Import Ical\" permission to \"manage content settings\".\n [jone]\n\n\n1.2 (2013-08-26)\n----------------\n\n- Workflow generation: sort worklists so that the result is constant.\n [jone]\n\n- Support remapping permission per workflow when it is ignored globally. #22\n [jone]\n\n- **Support for configuring visible roles in sharing view.**\n The specification now allows to define a list of roles which\n should appear one the sharing view.\n [jone]\n\n- **Context / workflow sensitive role translations for sharing view.**\n Dynamic roles: replacing Plone's default roles utilities,\n allowing us to change the translation of the role for the\n sharing view depending on the workflow of the current context.\n Lawgiver's new default role utility / adapter provides per-workflow\n translations of the roles.\n [jone]\n\n\n1.1 (2013-08-08)\n----------------\n\n- Ignore plone.resourceeditor permission for workflows.\n [jone]\n\n\n1.0 (2013-05-28)\n----------------\n\n- Initial implementation.\n [jone]", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/4teamwork/ftw.lawgiver", "keywords": "ftw lawgiver generate workflows dsl", "license": "GPL2", "maintainer": "", "maintainer_email": "", "name": "ftw.lawgiver", "package_url": "https://pypi.org/project/ftw.lawgiver/", "platform": "", "project_url": "https://pypi.org/project/ftw.lawgiver/", "project_urls": { "Homepage": "https://github.com/4teamwork/ftw.lawgiver" }, "release_url": "https://pypi.org/project/ftw.lawgiver/1.16.1/", "requires_dist": null, "requires_python": "", "summary": "Generate your Plone workflows by describing it in plain text with a DSL.", "version": "1.16.1" }, "last_serial": 5823337, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "19991b5f6f3f3a5ea2537bb784114fd6", "sha256": "78170463ec8729e07cf2e321f2246bad5da450bb36ef9586837ba136f942f187" }, "downloads": -1, "filename": "ftw.lawgiver-1.0.zip", "has_sig": false, "md5_digest": "19991b5f6f3f3a5ea2537bb784114fd6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 390688, "upload_time": "2013-05-28T15:59:45", "url": "https://files.pythonhosted.org/packages/64/46/1983a33c3012012c1d80ca783ec12960297428fcde2b04e8f86b68c9fa6c/ftw.lawgiver-1.0.zip" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "bebc451e02e2be6b834d53ecc899a3eb", "sha256": "c7d983028dea7b5eac6bc50655a66ec4ee5c00f02fef50c4622409fa8c4cf527" }, "downloads": -1, "filename": "ftw.lawgiver-1.1.zip", "has_sig": false, "md5_digest": "bebc451e02e2be6b834d53ecc899a3eb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 390886, "upload_time": "2013-08-08T08:49:21", "url": "https://files.pythonhosted.org/packages/98/82/d1e021a86978cc46e9094bd8dc841996862d6ea52405bc12282ea5bf0390/ftw.lawgiver-1.1.zip" } ], "1.10.0": [ { "comment_text": "", "digests": { "md5": "4dc6062ccbb5e0cdefa3b0575c829fb8", "sha256": "937914c2aec24da23d8fe378c1a4db38bf2ab7f7ba07c6160e005f2483d47b3a" }, "downloads": -1, "filename": "ftw.lawgiver-1.10.0.tar.gz", "has_sig": false, "md5_digest": "4dc6062ccbb5e0cdefa3b0575c829fb8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 635632, "upload_time": "2017-07-11T08:31:45", "url": "https://files.pythonhosted.org/packages/6f/b5/af8a6f870eaa35fb8e07e282ff4bd7fa6833720ca7b28f52690fa07f0cd9/ftw.lawgiver-1.10.0.tar.gz" } ], "1.10.1": [ { "comment_text": "", "digests": { "md5": "231304afd3e29fbaf7ef4511af88dc7f", "sha256": "2a53b057b68bf0658c529b9a2ea21720a04204d4322d593bdad0ae5a90bd1691" }, "downloads": -1, "filename": "ftw.lawgiver-1.10.1.tar.gz", "has_sig": false, "md5_digest": "231304afd3e29fbaf7ef4511af88dc7f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 636372, "upload_time": "2017-07-27T11:24:03", "url": "https://files.pythonhosted.org/packages/f0/3b/7ac7a1c3efb667174a174fd3ccb35879681938162932ed9180293d6f55c1/ftw.lawgiver-1.10.1.tar.gz" } ], "1.11.0": [ { "comment_text": "", "digests": { "md5": "ddea41c713c60b155a5cf3dd520ab360", "sha256": "d245a8d3ad5de35d39d54339f9a5d9f843bd399dbc87dbd8ff077bde8cb76171" }, "downloads": -1, "filename": "ftw.lawgiver-1.11.0.tar.gz", "has_sig": false, "md5_digest": "ddea41c713c60b155a5cf3dd520ab360", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 637290, "upload_time": "2017-12-06T07:45:54", "url": "https://files.pythonhosted.org/packages/26/9d/b3f6a9f9015e957689fea6e65a2fe655263c8eed54c092f556355a346f20/ftw.lawgiver-1.11.0.tar.gz" } ], "1.12.0": [ { "comment_text": "", "digests": { "md5": "2f03b2f37534e3fc445fef4d0c8affcc", "sha256": "d6c0c4370ecc4a49dc79f62c98fffa14191fad232d9f04b7f62c54f33b41dd02" }, "downloads": -1, "filename": "ftw.lawgiver-1.12.0.tar.gz", "has_sig": false, "md5_digest": "2f03b2f37534e3fc445fef4d0c8affcc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 637471, "upload_time": "2017-12-15T13:56:53", "url": "https://files.pythonhosted.org/packages/aa/0b/4c5c885038b58ce4b9a4d829ba6b87fda41e2bbd4d10818684f06e6700f2/ftw.lawgiver-1.12.0.tar.gz" } ], "1.13.0": [ { "comment_text": "", "digests": { "md5": "349036f84a3ff7bb3f1e743fa5ea5010", "sha256": "71f0c5654b5797a950c4640244ed09b208b6c900e94249aabaf0216b65264bf8" }, "downloads": -1, "filename": "ftw.lawgiver-1.13.0.tar.gz", "has_sig": false, "md5_digest": "349036f84a3ff7bb3f1e743fa5ea5010", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 638492, "upload_time": "2017-12-18T08:43:53", "url": "https://files.pythonhosted.org/packages/5a/7e/65b343571d36702b0c2eaa83bd5785a7a6999faa7a0a34e9fa5e7e53be55/ftw.lawgiver-1.13.0.tar.gz" } ], "1.14.0": [ { "comment_text": "", "digests": { "md5": "85a651dfc41b015a1416da9e089b75ce", "sha256": "75c9ddd339d70f1e49af62ffc40c2a6e25a8d01e71a7a6faade0e81cfce6eda2" }, "downloads": -1, "filename": "ftw.lawgiver-1.14.0.tar.gz", "has_sig": false, "md5_digest": "85a651dfc41b015a1416da9e089b75ce", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 643292, "upload_time": "2018-01-08T11:52:16", "url": "https://files.pythonhosted.org/packages/8f/b7/fd4920c4075f894dab798b7312ebdf3d7d1245e42378789b9c7a78ad2189/ftw.lawgiver-1.14.0.tar.gz" } ], "1.14.1": [ { "comment_text": "", "digests": { "md5": "e10df955c47d712ac498a5ff52da4dea", "sha256": "6c00e65868fb1fde0d7b686eb19707ae1b6cc2a9f1f809c9257698a80c9599c6" }, "downloads": -1, "filename": "ftw.lawgiver-1.14.1.tar.gz", "has_sig": false, "md5_digest": "e10df955c47d712ac498a5ff52da4dea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 643473, "upload_time": "2018-01-15T17:32:43", "url": "https://files.pythonhosted.org/packages/80/7a/bd8f409136c672f15b46f6a4c96c34c14cc6f708a6fd8cb6bfc74359ecbe/ftw.lawgiver-1.14.1.tar.gz" } ], "1.15.0": [ { "comment_text": "", "digests": { "md5": "32e0cbfe005cdffb524d82871fe17f98", "sha256": "3ef22bbc14e27bdc153f0cc234bd6feeb1853fee981c72397c2042dca762ea52" }, "downloads": -1, "filename": "ftw.lawgiver-1.15.0.tar.gz", "has_sig": false, "md5_digest": "32e0cbfe005cdffb524d82871fe17f98", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 648032, "upload_time": "2018-08-03T08:09:04", "url": "https://files.pythonhosted.org/packages/3c/19/470222bbf3062df6402332c1aca7c51ac30fc7dff033f471abdee5c5307b/ftw.lawgiver-1.15.0.tar.gz" } ], "1.16.0": [ { "comment_text": "", "digests": { "md5": "0a95d3b93dc4ebfd787ba89d518f133a", "sha256": "212d0cc27aba0686c3d78c7891dcc93dea7de9504cfef8fdac691799a9e3d291" }, "downloads": -1, "filename": "ftw.lawgiver-1.16.0.tar.gz", "has_sig": false, "md5_digest": "0a95d3b93dc4ebfd787ba89d518f133a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 649325, "upload_time": "2018-08-07T07:00:41", "url": "https://files.pythonhosted.org/packages/91/b5/b4a36112b508f31b22cfa15f544266b9e481db2a1c6d43195309b8958bbd/ftw.lawgiver-1.16.0.tar.gz" } ], "1.16.1": [ { "comment_text": "", "digests": { "md5": "2b2aac611641a736978c426fb78d2244", "sha256": "153296f30200bf6287cb4a5c9c50534aa7328d671fe2409f70627a87abd74572" }, "downloads": -1, "filename": "ftw.lawgiver-1.16.1.tar.gz", "has_sig": false, "md5_digest": "2b2aac611641a736978c426fb78d2244", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 650170, "upload_time": "2019-09-12T10:07:24", "url": "https://files.pythonhosted.org/packages/48/db/c566160257f9537602b951b901f10fa8604b97f9dcf6221f6f0cf41b3292/ftw.lawgiver-1.16.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "117d90f4507816e592b95b0f07589d81", "sha256": "f92b1536354fd96a76ae521514f40dc5a13b97ef8f32b978fa1c733c34226196" }, "downloads": -1, "filename": "ftw.lawgiver-1.2.zip", "has_sig": false, "md5_digest": "117d90f4507816e592b95b0f07589d81", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 406211, "upload_time": "2013-08-26T14:22:03", "url": "https://files.pythonhosted.org/packages/55/6b/954c38f1d00ac74737bc0fc63021826f328406942d7a4a7bd493484de15d/ftw.lawgiver-1.2.zip" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "f1ab8113dfc9fe64540c691c33c1f786", "sha256": "890b43362b0acc3b9235d8f93c8978191d456936ac5b551e42beddd72008a381" }, "downloads": -1, "filename": "ftw.lawgiver-1.2.1.zip", "has_sig": false, "md5_digest": "f1ab8113dfc9fe64540c691c33c1f786", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 406834, "upload_time": "2013-11-26T20:46:27", "url": "https://files.pythonhosted.org/packages/f2/c7/b62006ddf2c8cfdc0925fa7d20e1fa7f41caf1a35280b9f481e2bc87c6bb/ftw.lawgiver-1.2.1.zip" } ], "1.2.2": [ { "comment_text": "", "digests": { "md5": "ac3f7b9405f2a0bfb9ec31bf5839bd61", "sha256": "40146a4715f5a024f6105d028f5dbda65d18dc38bdb953fff6288c82d179d7ca" }, "downloads": -1, "filename": "ftw.lawgiver-1.2.2.zip", "has_sig": false, "md5_digest": "ac3f7b9405f2a0bfb9ec31bf5839bd61", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 408230, "upload_time": "2014-01-09T08:54:31", "url": "https://files.pythonhosted.org/packages/a2/4b/1c08aad0d453bfe3dae31fa17d6d31e0e00bf6110f118fea1f8dcff80eaa/ftw.lawgiver-1.2.2.zip" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "3d7e7a82b60a317d752fb56bc751bd88", "sha256": "e9803df6c634164c31c0fef984b1efcc1d24f43251324ed2c39440b563d4934c" }, "downloads": -1, "filename": "ftw.lawgiver-1.3.0.zip", "has_sig": false, "md5_digest": "3d7e7a82b60a317d752fb56bc751bd88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 673929, "upload_time": "2014-05-19T12:24:07", "url": "https://files.pythonhosted.org/packages/7b/47/3748b32a3446b76f622cfdfda6be559f517f8b994b1e1018312558f4dd3c/ftw.lawgiver-1.3.0.zip" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "2fc14a45c468d2d9afe032c696dd32b1", "sha256": "fbe30f7a196339aa423ed1947c24d8419c41c19ba836f5310fadc5968fb33f75" }, "downloads": -1, "filename": "ftw.lawgiver-1.3.1.zip", "has_sig": false, "md5_digest": "2fc14a45c468d2d9afe032c696dd32b1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 674832, "upload_time": "2014-05-28T12:55:36", "url": "https://files.pythonhosted.org/packages/64/cc/beeb97d12eef9919b12b0938548fc230c57d605fdaa96f4aaea12286f766/ftw.lawgiver-1.3.1.zip" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "cefef74569a5f2a04f9915a206b29665", "sha256": "bd2ef21528d60d2da0cab75eacd2344908b718bc64d0dfd857bb7e46a097ad8c" }, "downloads": -1, "filename": "ftw.lawgiver-1.4.0.zip", "has_sig": false, "md5_digest": "cefef74569a5f2a04f9915a206b29665", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 680566, "upload_time": "2014-09-09T08:52:05", "url": "https://files.pythonhosted.org/packages/d9/d3/793e357d2fcba26d2c1ce34c2566cef61951c02ec1ebbc099afd343bb7d5/ftw.lawgiver-1.4.0.zip" } ], "1.5.0": [ { "comment_text": "", "digests": { "md5": "53d1bda75e17aed8a385bc6df07123fc", "sha256": "2c5d2dc610e98be42972d7cf41170eae022d04bd456a755863af79d95b328d05" }, "downloads": -1, "filename": "ftw.lawgiver-1.5.0.zip", "has_sig": false, "md5_digest": "53d1bda75e17aed8a385bc6df07123fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 683807, "upload_time": "2014-12-08T06:25:19", "url": "https://files.pythonhosted.org/packages/87/ec/aba89d549daedd714daf031a2ea417def80d2dda339c577039494461c47e/ftw.lawgiver-1.5.0.zip" } ], "1.6.0": [ { "comment_text": "", "digests": { "md5": "11f6f168da69184497e7139964b269f1", "sha256": "7fae4fa0487da68de5c257ad6523dc3ca802d51e06a69507ef35fb9a767edf4e" }, "downloads": -1, "filename": "ftw.lawgiver-1.6.0.zip", "has_sig": false, "md5_digest": "11f6f168da69184497e7139964b269f1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 685061, "upload_time": "2015-05-21T09:29:35", "url": "https://files.pythonhosted.org/packages/d1/e3/1c5d5ad9945b598bc0cfa77fc5f0b77c12bb860fac6b2d42a044100e31ce/ftw.lawgiver-1.6.0.zip" } ], "1.6.1": [ { "comment_text": "", "digests": { "md5": "9ebf2042dbffa46e91c577d035f0f527", "sha256": "c17b144e9660c0af93ba3b59a457d0c48e61fbf94c35908a2dd230f548eb412b" }, "downloads": -1, "filename": "ftw.lawgiver-1.6.1.tar.gz", "has_sig": false, "md5_digest": "9ebf2042dbffa46e91c577d035f0f527", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 627655, "upload_time": "2015-10-08T11:27:51", "url": "https://files.pythonhosted.org/packages/d8/cb/5ac5ad97e8a03f763e855b67990fbb1fb9a2fb1666f2961c6ff7d5beeaef/ftw.lawgiver-1.6.1.tar.gz" } ], "1.6.2": [ { "comment_text": "", "digests": { "md5": "961bd386f14f67c9902f20c7970ac69f", "sha256": "07f7d9acedd6c621078d2641433c98a7fff538ad6e23b80f318f7360ea97736f" }, "downloads": -1, "filename": "ftw.lawgiver-1.6.2.tar.gz", "has_sig": false, "md5_digest": "961bd386f14f67c9902f20c7970ac69f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 627784, "upload_time": "2015-11-16T11:18:03", "url": "https://files.pythonhosted.org/packages/93/4b/859a7ce9bbcf10374c18f295031a80e295b7133ebcedbd5c1ddb9e88f4b4/ftw.lawgiver-1.6.2.tar.gz" } ], "1.7.0": [ { "comment_text": "", "digests": { "md5": "cc58b9d775b9e3d762256761cf85e64d", "sha256": "012474d4c5ad9b3a675f66087fef403cba00195b05513d9966cdcc68cec1332c" }, "downloads": -1, "filename": "ftw.lawgiver-1.7.0.tar.gz", "has_sig": false, "md5_digest": "cc58b9d775b9e3d762256761cf85e64d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 628557, "upload_time": "2016-05-02T15:43:52", "url": "https://files.pythonhosted.org/packages/73/1a/14bee3724dc9b7a5232a52ffa6487c22390f31b4cb6db77ad5d69429f94e/ftw.lawgiver-1.7.0.tar.gz" } ], "1.8.0": [ { "comment_text": "", "digests": { "md5": "ffc0c935ac6d14a5f0dd8051d3876490", "sha256": "5c4cbbd431d866647bdbf093db182bd7969b270aa03ca521ef76b5c145016d0c" }, "downloads": -1, "filename": "ftw.lawgiver-1.8.0.tar.gz", "has_sig": false, "md5_digest": "ffc0c935ac6d14a5f0dd8051d3876490", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 629100, "upload_time": "2016-06-30T06:54:14", "url": "https://files.pythonhosted.org/packages/77/70/47de79093f7cd7b88c617854bf7ed1ab1252662d0548828512ee5181b8e1/ftw.lawgiver-1.8.0.tar.gz" } ], "1.9.0": [ { "comment_text": "", "digests": { "md5": "ae8d2c32c9853ca5081e30796b9b218d", "sha256": "88c98ca0e1fbe4e9a3898b20dc6c9bd1b515acea653984c335f2ba7b1328c190" }, "downloads": -1, "filename": "ftw.lawgiver-1.9.0.tar.gz", "has_sig": false, "md5_digest": "ae8d2c32c9853ca5081e30796b9b218d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 631692, "upload_time": "2017-01-03T15:39:47", "url": "https://files.pythonhosted.org/packages/1d/a2/4d887279cd351fc14819bfe680378a37cb97b060d6e5aa9b071c5b961d15/ftw.lawgiver-1.9.0.tar.gz" } ], "1.9.1": [ { "comment_text": "", "digests": { "md5": "961a97537af92c58eda5d2e7ecb092c6", "sha256": "795767070b77bd43b1abce39751a71428b936dbe1908563ebaed21b9b28d59b7" }, "downloads": -1, "filename": "ftw.lawgiver-1.9.1.tar.gz", "has_sig": false, "md5_digest": "961a97537af92c58eda5d2e7ecb092c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 633087, "upload_time": "2017-07-10T08:20:15", "url": "https://files.pythonhosted.org/packages/e0/c7/3ce562f992868859b2115b679be21e837f8fc1d2599785be1f06fd45fcce/ftw.lawgiver-1.9.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2b2aac611641a736978c426fb78d2244", "sha256": "153296f30200bf6287cb4a5c9c50534aa7328d671fe2409f70627a87abd74572" }, "downloads": -1, "filename": "ftw.lawgiver-1.16.1.tar.gz", "has_sig": false, "md5_digest": "2b2aac611641a736978c426fb78d2244", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 650170, "upload_time": "2019-09-12T10:07:24", "url": "https://files.pythonhosted.org/packages/48/db/c566160257f9537602b951b901f10fa8604b97f9dcf6221f6f0cf41b3292/ftw.lawgiver-1.16.1.tar.gz" } ] }