{ "info": { "author": "Martin Aspeli", "author_email": "optilude@gmail.com", "bugtrack_url": null, "classifiers": [ "Framework :: Plone", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "===============\ncollective.wtf\n===============\n\n by Martin Aspeli \n \nThis package contains tools for working with DC Workflow definitions via\nspreadsheets (or rather, CSV format) as well as debugging aids to make it\neasier to work with security and workflow in Zope 2 and Plone.\n\nIt consists of:\n\n - A GenericSetup exporter that can dump a workflow definition to a CSV file\n - A GenericSetup importer that can create a workflow definition from a CSV\n file\n - An in-browser tool to sanity-check a workflow\n - A browser view to dump a workflow in the site to CSV as a one-off\n - A browser view to show the roles of a user in a given context\n - Utility functions to trigger automatic transitions on an object, as well as\n on its parent.\n \nCSV import/export\n=================\n\nPlease note that the CSV format is not completely equivalent to the standard \nXML-based GenericSetup format to import/export workflow definitions. If you\nrequire the full power of DCWorkflow, you should continue to use the XML\nbased format. This is not (just) due to laziness - the CSV format has been \nsimplified to make common operations easy.\n\nFor an example CSV file, see\n \n collective/wtf/tests/profiles/testing/test_wf.csv.\n \nTo be imported as part of a GenericSetup extension profile, a file like this\nwould normally go in\n\n profiles/default/workflow_csv/wf_name.csv \n \nwhere wf_name is the name of the workflow in portal_workflow.\n\nNote that if a full workflow definition does exist (e.g. in \nprofiles/default/workflows/my_workflow/definition.xml), the CSV importer will\n*not* attempt to run an import, so as not to conflict or overwrite changes.\n\nTo download a workflow definition in CSV format as a one-off, type a URL like\nthis into your browser:\n\n http://localhost:8080/Plone/portal_workflow/my_workflow/@@to-csv\n\nHere, \"Plone\" is the name of the Plone instance and \"my_workflow\" is the name\nof your workflow definition. You will be asked to download a CSV file.\n\nWorkflow sanity checker\n=======================\n\nTo invoke the sanity checker, type a URL like this into your browser:\n\n http://localhost:8080/Plone/portal_workflow/my_workflow/@@sanity-check\n \nAgain, \"Plone\" is the name of the Plone instance and \"my_workflow\" is the name\nof the workflow definition. The output will be written to the browser window\nin plain text.\n\nOther debugging aids\n====================\n\nTo view the current roles of a given user in a given context, type a URL like\nthis into your browser when logged in as a Manager user:\n\n http://localhost:8080/Plone/context/@@display-roles-in-context?user=\n \nAgain, \"Plone\" is the name of the Plone instance. \"context\" could be any \nobject. should be replaced by the login name/id of the user you \nwant to fetch roles for. The output will be written to the browser window in\nplain text.\n\nCSV file specification\n======================\n\nThis section details the CSV file format.\n\nGeneral\n-------\n\nThe CSV file format generally relies on key-value pairs, where keys are in\nthe first column (A) and values in the second column (B). Key names are not\ncase sensitive, may substitute hyphens for spaces, and may optionally contain\na trailing colon. For example, the following are all equivalent::\n\n Some key:,some_value\n some key:,some_value\n some-key , some_value\n\nThe file is sub-divided into sections. A section begins with a row containing\nthe section name in square brackets, and ends with at least one blank row.\nFor example::\n\n [SomeSection]\n Some key:,some_value\n Some other key:,another_value\n \n [AnotherSection]\n ...\n \nThe various sections are listed below, in more detail.\n\nThe [Workflow] section\n----------------------\n\nThis is generally the first section in the file. It contains information\nabout the workflow as a whole, with the following keys. Keys marked with a\n* are required.\n\n Id* -- The name of the workflow as it will be installed in portal_workflow.\n\n Initial state* -- The name of the initial state of the workflow. Must match\n the id of a [State] section elsewhere in the file.\n \n Title -- A human-friendly title for the workflow.\n \n Description -- A human-friendly description for the workflow.\n \n Type -- The meta_type of the workflow. Defaults to 'Workflow', which is the\n standard DCWorkflow definition type. Note that if you have a custom\n workflow, there is no guarantee that collective.wtf will be able to parse\n it, so be careful.\n \n State variable -- The workflow variable that holds the current state. For\n the primary workflow of a Plone content object, this should be\n 'review_state', which is the default. However, if you are designing a\n secondary workflow in a multi-workflow chain, it may need a different\n state variable.\n\nFor example::\n\n [Workflow]\n Id:,test_workflow\n Title:,Test workflow\n Description:,Description of workflow\n Initial state:,state_one\n \nThe [State] section\n-------------------\n\nThis section defines a single workflow state. It must end with a permissions\ntable - see below.\n\n Id* -- A unique name for the state.\n \n Title* -- A human-friendly title.\n \n Description -- A human-friendly description.\n \n Transitions -- A comma-separated list of transitions. Note that this should\n be limited to a single cell. Hence, you will need double quotes around\n the list, e.g. \"transition_1, transition_2\". Each transition listed\n must match the id of a [Transition] section elsewhere in the file.\n \n Worklist -- The name of a worklist for objects in this state, if one is\n required.\n \n Worklist label -- A human-friendly label for the worklist.\n \n Worklist guard permission -- The name of a permission used to guard the\n worklist, if required.\n \n Worklist guard expression -- A TALES expression used to guard the worklist,\n if required.\n \n Worklist guard role -- The name of a role used to guard the workflist, if\n required.\n\nFor example::\n\n [State]\n Id:,state_one\n Title:,State one\n Description:,Description of state one\n Transitions:,\"to_state_two,to_state_three\"\n Worklist:,State one worklist\n Worklist label:,Worklist stuff goes here\n Worklist guard permission:,Review portal content\n Worklist guard expression:,python:True==True\n Worklist guard role:,Manager\n Permissions, Acquire, Manager, Member, Owner\n View, Y, Y, N, Y\n Access contents information, Y, Y, N, Y\n Modify portal content, N, Y, N, N\n\nThe permissions table\n---------------------\n\nAt the end of a [State] section, before the blank line that signals the end\nof that section, there must be a table of permissions for this state. The\ntable may look like this::\n\n Permissions, Acquire, Manager, Member, Owner\n View, Y, Y, N, Y\n Access contents information, Y, Y, N, Y\n Modify portal content, N, Y, N, N\n \nNote that the additional whitespace here is purely for readability, and is\noptional.\n\nThe permissions table is created by having the pseudo-key 'Permissions' in\ncolumn A. Column B is used to indicate whether a given permission is acquired\nfrom the parent object or not. By convention, the header row should contain\nthe word 'Acquire' here. Subsequent rows should contain role names.\n\nUnderneath the header row, the first column should contain the names of\npermissions. Subsequent columns indicate whether the given role has the\ngiven permission in this workflow state. A case-insensitive value of 'Y', \n'*', 'X' or 'Yes' indicates true. Any other value (including blanks, 'N' or\n'No') indicates false.\n\nThe [Transition] section\n------------------------\n\nThis section defines a transition between two states. It may contain the\nfollowing keys:\n\n Id* -- A unique identifier for the transition\n \n Title -- A human-friendly title for the transition.\n\n Description -- A human-friendly description for the transition.\n\n URL -- A string containing a URL that will be used when the user clicks\n the transition in the workflow menu. May contain the special variables\n %(portal_url)s, %(folder_url)s, %(content_url)s and %(user_id)s. If not\n given, the default view will be used.\n\n Target state -- The state that the workflow should move to after this\n transition has been executed. If omitted, the transition will not cause\n a state change. If included, it must match the id of a [State] section\n defined elsewhere in the file.\n \n Trigger -- One of 'User' or 'Automatic'. Defaults to 'User'. An automatic\n transition is one which is run automatically when the workflow enters a\n state for which the automatic transition is a valid exit transition.\n Automatic transitions are often used with transition guards to\n automatically advance the workflow in certain situations, and/or with\n transition scripts that execute on the automatic transition.\n \n Guard permission -- The name of a permission that is required before this\n transition is made available.\n \n Guard expression -- A TALES expression that must be true before this\n transition is made available.\n \n Guard role -- The name of a role that the current user must have before\n this transition is made available.\n \n Script before -- A script to execute before the transition effects a state\n change. This may either contain a simple string, in which case it must\n match the id of a [Script] section elsewhere in the file, or a dotted\n name to an external method, e.g. \n 'my.product.Extensions.script_name.function_name', where 'my.product' is\n the name of a product that contains an Extensions/ folder, 'script_name'\n is the name of a .py file in that Extensions/ folder, and 'function_name'\n is the name of a function in that .py file. The function must take two\n parameters: self, and a state_change, a StateChangeInfo object. In this\n case, the importer will create a new External Method with the appropriate\n module ('my.product.script_name') and function ('function_name'), give it\n and id based on the script and function name (in this case,\n 'script_name.function_name'), and set this as the script before.\n \n Script after -- A script to execute after the transition effects a state\n change. This may contain the same values as Script before.\n \nFor example::\n\n [Transition]\n Id:,to_state_one\n Title:,Make it state one\n Description:,Make it go to state one\n Target state:,state_one\n Trigger:,User\n Guard permission:,Modify portal content,View\n Guard expression:,python:True==True\n Guard role:,Manager\n Script before:,shared_script\n Script after:,collective.wtf.Extensions.test_scripts.inline_test_one\n \nThe [Script] section\n--------------------\n\nThis may be used to define a script explicitly. Only external method scripts\nare supported. Note that single-use external methods can be defined \"inline\"\nusing the notation described under 'The [Transition] section' above.\n\n Id* -- The id of the script\n \n Type* -- Should be 'External Method'. In the future, other types of script\n may be supported.\n \n Module* -- The module where the external method is defined. Note that this\n should not contain the 'Extensions' directory.\n \n Function* -- The name of the function to execute when the external method\n is run.\n\nFor example::\n\n [Script]\n Id:,shared_script\n Type:,External Method\n Module:, collective.wtf.test_scripts\n Function:,script_section_test\n\nChangelog\n=========\n\n1.0b9\n-----\n\n* Don't make assumptions about the csv dialect on import. Instead, sniff the\n first 1024 bytes.\n [mj]\n\n1.0b8\n-----\n\n* Avoid creating a ghost workflow_csv folder in the current directory.\n [optilude]\n\n1.0b7\n-----\n\n* Add CMF 2.2 / Plone 4 support. Note that the new workflow options (like\n \"manager bypass\" and \"creation guard\") are not (yet) supported.\n [optilude]\n\n1.0b6\n-----\n\n* Add support for setting the state variable, with the 'State variable' option\n to the main workflow section.\n [optilude]\n\n1.0b5\n-----\n\n* Now imports/exports meta_type, in order to support workflows defined with\n collective.reactiveworkflow. This uses the option 'Type' in the main\n workflow section.\n [optildue]\n\n1.0b5\n-----\n\n* Added utility methods to trigger automatic transitions on self and on\n the parent, borrowed from Products.ReactiveWorkflow, but made to be useable\n directly from a script rather than only in an event handler.\n [optilude]\n\n* Improve documentation\n [optilude]\n\n* Add inline script support\n [optilude]\n\n1.0b4\n-----\n\n* Add script support\n [elro]\n\n1.0b2\n-----\n\n* Add the ability to display roles in any context via a simple browser view\n [optilude]", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://plone.org", "keywords": "plone workflow genericsetup", "license": "LGPL", "maintainer": null, "maintainer_email": null, "name": "collective.wtf", "package_url": "https://pypi.org/project/collective.wtf/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/collective.wtf/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://plone.org" }, "release_url": "https://pypi.org/project/collective.wtf/1.0b9/", "requires_dist": null, "requires_python": null, "summary": "GenericSetup importer and exporter for workflow definitions that uses CSV instead of XML", "version": "1.0b9" }, "last_serial": 657010, "releases": { "1.0a1": [ { "comment_text": "", "digests": { "md5": "e969eb128156c8502643862628a2d051", "sha256": "6a49e66012f7a15199df72217d9e60056b5945c2918ca1fda9782844e5e78388" }, "downloads": -1, "filename": "collective.wtf-1.0a1-py2.4.egg", "has_sig": false, "md5_digest": "e969eb128156c8502643862628a2d051", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 38061, "upload_time": "2008-03-21T20:04:33", "url": "https://files.pythonhosted.org/packages/7d/71/5b661855f2af6d975b804ea5c9c66eeadddfc0fea8ff9c097822e68a44f0/collective.wtf-1.0a1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "ec5dc0d7b0ef6f4854ebc088a57a26b5", "sha256": "2e79a92b097ae72056995b5df2fd739c724e03233aa9aad5f7d62f167e0eb097" }, "downloads": -1, "filename": "collective.wtf-1.0a1.tar.gz", "has_sig": false, "md5_digest": "ec5dc0d7b0ef6f4854ebc088a57a26b5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13651, "upload_time": "2008-03-21T20:04:33", "url": "https://files.pythonhosted.org/packages/d3/93/4ebb01673a68ae9a9ea0dc910619bc25554bba422c346a3d32ca499a98a8/collective.wtf-1.0a1.tar.gz" } ], "1.0a2": [ { "comment_text": "", "digests": { "md5": "ba625f729129b7b1d1c61a4927dd6d47", "sha256": "9e43c443918f0ee569badf03bc053a4a1ef1f503dc7c044ed66cf080f24021fc" }, "downloads": -1, "filename": "collective.wtf-1.0a2-py2.4.egg", "has_sig": false, "md5_digest": "ba625f729129b7b1d1c61a4927dd6d47", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 38352, "upload_time": "2008-03-25T23:26:28", "url": "https://files.pythonhosted.org/packages/42/44/baf27f5d397e88da7c2d52d9671e4deadf5c16eaa4e6b8a10ca6fc61d5c5/collective.wtf-1.0a2-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "4957616bc2c5fc57f7dfbf01e203555b", "sha256": "c2aef1133579ceb7ab9d17f0fd25a3f822d1dc264cb620958da59ccd1669f49e" }, "downloads": -1, "filename": "collective.wtf-1.0a2.tar.gz", "has_sig": false, "md5_digest": "4957616bc2c5fc57f7dfbf01e203555b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13788, "upload_time": "2008-03-25T23:26:28", "url": "https://files.pythonhosted.org/packages/cc/f4/3be8c280056d4f5e49e1c4fa39fb44dce02fb547d749b19c2a136dbef814/collective.wtf-1.0a2.tar.gz" } ], "1.0b1": [ { "comment_text": "", "digests": { "md5": "24d2fc5bd30625a4b950fad2b38b67ea", "sha256": "aca52c90a85b279b5e7f4ac1af1c98a8fc2e3b862f1b06e59877557ad77a5c13" }, "downloads": -1, "filename": "collective.wtf-1.0b1-py2.4.egg", "has_sig": false, "md5_digest": "24d2fc5bd30625a4b950fad2b38b67ea", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 44100, "upload_time": "2008-03-28T01:43:16", "url": "https://files.pythonhosted.org/packages/df/34/ce71ae21079a0c2bb4aa813297028f79d42b84d9ab96e8f42f47a9499f06/collective.wtf-1.0b1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "eb6b6accb79b3d51c2fa968122c3a442", "sha256": "5407b4c67344c0e58fd643cb5e481f3d7b9824eb25a67397b3a8da254b4989fa" }, "downloads": -1, "filename": "collective.wtf-1.0b1.tar.gz", "has_sig": false, "md5_digest": "eb6b6accb79b3d51c2fa968122c3a442", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15506, "upload_time": "2008-03-28T01:43:16", "url": "https://files.pythonhosted.org/packages/27/e8/9a2d34745f0d6932ac2d8daa9452a2ec8467ae4b63a862ec77f9da74b842/collective.wtf-1.0b1.tar.gz" } ], "1.0b2": [ { "comment_text": "", "digests": { "md5": "3d097ab18b073de7ae6ed26226c5e40e", "sha256": "f238c6b3dcd094b849b3b57a26ed3472a36c97f69be9f0dce8335b828aecaf77" }, "downloads": -1, "filename": "collective.wtf-1.0b2-py2.4.egg", "has_sig": false, "md5_digest": "3d097ab18b073de7ae6ed26226c5e40e", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 49850, "upload_time": "2008-04-23T01:02:35", "url": "https://files.pythonhosted.org/packages/43/03/0882584a7502dede18a68bd4dca8dbb2430ebad61dbf1451ce6393092cb0/collective.wtf-1.0b2-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "71abe8738279953abf26a201ae513b66", "sha256": "53aea6ce4458312dfd0d99a30c1a4656a5c1cd9bd1e42211fe3596ee1944c878" }, "downloads": -1, "filename": "collective.wtf-1.0b2.tar.gz", "has_sig": false, "md5_digest": "71abe8738279953abf26a201ae513b66", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16430, "upload_time": "2008-04-23T01:02:33", "url": "https://files.pythonhosted.org/packages/ea/d8/670002625bc6c53d0699050232d0baf6b49380a2ab4fd219acbc06283544/collective.wtf-1.0b2.tar.gz" } ], "1.0b3": [ { "comment_text": "", "digests": { "md5": "8cf0c00e7e694441ee9a19902592cf06", "sha256": "3cff6578bc0850b744cd7a96c978fbe97e804f7ef4d7b43e4d1524450f1a3ea8" }, "downloads": -1, "filename": "collective.wtf-1.0b3-py2.4.egg", "has_sig": false, "md5_digest": "8cf0c00e7e694441ee9a19902592cf06", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 48609, "upload_time": "2008-08-21T21:21:05", "url": "https://files.pythonhosted.org/packages/d4/74/4ebd2f38788afbfed5607dd32736a3a5f92c8b8103b1278deb34c92335af/collective.wtf-1.0b3-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "1a6637e7e013382b840c739cc075b4db", "sha256": "c29af211588758d2f925c3e377c4e9e18797cdd441ddf45c3a34e3703eb337df" }, "downloads": -1, "filename": "collective.wtf-1.0b3.tar.gz", "has_sig": false, "md5_digest": "1a6637e7e013382b840c739cc075b4db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17479, "upload_time": "2008-08-21T21:21:05", "url": "https://files.pythonhosted.org/packages/58/41/6d55d5245e17c95262ee41f636a3f9d4f8698070ae52cf57566cbfcdfc3e/collective.wtf-1.0b3.tar.gz" } ], "1.0b4": [ { "comment_text": "", "digests": { "md5": "44976b5af7fb9010dee2b3d2592f2152", "sha256": "3657c3da7ca9b1cdcfe63b245d21e35f5b2a47ee1765e46afd774bd8d806905e" }, "downloads": -1, "filename": "collective.wtf-1.0b4-py2.4.egg", "has_sig": false, "md5_digest": "44976b5af7fb9010dee2b3d2592f2152", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 48582, "upload_time": "2008-08-21T23:01:04", "url": "https://files.pythonhosted.org/packages/1f/f1/a81eb0e79e4fe7dd23bd4261e61326e2e8e8be0510311937361f8015aafc/collective.wtf-1.0b4-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "f027c317fefb2b10178537507af43a8a", "sha256": "2561a5f9081efded0a6e3f4af744c4f8def6293e5ae1363b14951579c4eb6526" }, "downloads": -1, "filename": "collective.wtf-1.0b4.tar.gz", "has_sig": false, "md5_digest": "f027c317fefb2b10178537507af43a8a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17429, "upload_time": "2008-08-21T23:01:04", "url": "https://files.pythonhosted.org/packages/90/b4/511c904607b92b759cb776fc0f391a616da4d0dc98c00785fd81e9575509/collective.wtf-1.0b4.tar.gz" } ], "1.0b5": [ { "comment_text": "", "digests": { "md5": "b8b5138e2b6f95484a5c2b7259a8a5ca", "sha256": "62ca17f8e7d8ed5f80a77bb881e309a081fed06b2a5cbbb232a5c0c8dec888ad" }, "downloads": -1, "filename": "collective.wtf-1.0b5.tar.gz", "has_sig": false, "md5_digest": "b8b5138e2b6f95484a5c2b7259a8a5ca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21443, "upload_time": "2009-03-02T10:03:20", "url": "https://files.pythonhosted.org/packages/23/3f/84745d82370e542ace6e6756d8d09745c9c7f3a73dc95a557fade3b18a5f/collective.wtf-1.0b5.tar.gz" } ], "1.0b6": [ { "comment_text": "", "digests": { "md5": "0fd215ccfbdc2e2b86552055559648ba", "sha256": "cf34550c43b845bd4e951462b6831534e35423d4a09699e08b4d46b296ec04b1" }, "downloads": -1, "filename": "collective.wtf-1.0b6.tar.gz", "has_sig": false, "md5_digest": "0fd215ccfbdc2e2b86552055559648ba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21791, "upload_time": "2009-04-02T18:11:27", "url": "https://files.pythonhosted.org/packages/31/55/33fce00c26c08413d1c29fca93e3f661c3372e65dda96767af51ba97c12b/collective.wtf-1.0b6.tar.gz" } ], "1.0b7": [ { "comment_text": "", "digests": { "md5": "2736784119a8ae30bebbe20f513f052b", "sha256": "7c0e6ce29ada7b2cf5f579d5a9143f29ceecd3bf4d330092d14483a2316f8c98" }, "downloads": -1, "filename": "collective.wtf-1.0b7.tar.gz", "has_sig": false, "md5_digest": "2736784119a8ae30bebbe20f513f052b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23375, "upload_time": "2009-11-17T15:27:13", "url": "https://files.pythonhosted.org/packages/9a/47/99b1fef331b01246cd5d01911109b6f6e4bc684d4d74e2f74767291b0a95/collective.wtf-1.0b7.tar.gz" } ], "1.0b8": [ { "comment_text": "", "digests": { "md5": "8b128797faa2fff5bdd9df074f3f31be", "sha256": "7c8ef03ee078549ba739343bbe255b3b00ca92f88a8d2f44049d29f81ab05edd" }, "downloads": -1, "filename": "collective.wtf-1.0b8.tar.gz", "has_sig": false, "md5_digest": "8b128797faa2fff5bdd9df074f3f31be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23407, "upload_time": "2009-12-29T12:06:46", "url": "https://files.pythonhosted.org/packages/30/e0/007fe3b9a8f2bb2ef21529d137bcc82b1031403946ddcf1328917b4444e1/collective.wtf-1.0b8.tar.gz" } ], "1.0b9": [ { "comment_text": "", "digests": { "md5": "2da42cc7581998dae8eb89e7792da42e", "sha256": "b6128e1f16fa07ceefaf1df9ccc839af0f07cdfc2e944d6c3ae87ff2ab3726cd" }, "downloads": -1, "filename": "collective.wtf-1.0b9.zip", "has_sig": false, "md5_digest": "2da42cc7581998dae8eb89e7792da42e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39898, "upload_time": "2010-02-06T16:00:28", "url": "https://files.pythonhosted.org/packages/75/49/2dab589ec41e1240f0abbbe157ff9b272047783de1897e4f6639deee5693/collective.wtf-1.0b9.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2da42cc7581998dae8eb89e7792da42e", "sha256": "b6128e1f16fa07ceefaf1df9ccc839af0f07cdfc2e944d6c3ae87ff2ab3726cd" }, "downloads": -1, "filename": "collective.wtf-1.0b9.zip", "has_sig": false, "md5_digest": "2da42cc7581998dae8eb89e7792da42e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39898, "upload_time": "2010-02-06T16:00:28", "url": "https://files.pythonhosted.org/packages/75/49/2dab589ec41e1240f0abbbe157ff9b272047783de1897e4f6639deee5693/collective.wtf-1.0b9.zip" } ] }