{ "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.builder\n===========\n\nCreate Plone objects in tests with the\n`Builder Pattern `_.\n\nThe builder pattern simplifies constructing objects.\nIn tests we often need to create Plone objects, sometimes a single object,\nsometimes a whole graph of objects.\nUsing the builder pattern allows us to do this in a DRY way, so that we do not\nrepeat this over and over.\n\n.. code:: python\n\n from ftw.builder import create\n from ftw.builder import Builder\n\n def test_foo(self):\n folder = create(Builder('folder')\n .titled('My Folder')\n .in_state('published'))\n\n\n.. contents:: Table of Contents\n\nInstallation\n------------\n\nAdd ``ftw.builder`` as (test-) dependency to your package in ``setup.py``:\n\n.. code:: python\n\n tests_require = [\n 'ftw.builder',\n ]\n\n setup(name='my.package',\n tests_require=tests_require,\n extras_require={'tests': tests_require})\n\n\nUsage\n-----\n\nSetup builder session in your testcase\n\n.. code:: python\n\n from ftw.builder import session\n\n class TestPerson(unittest2.TestCase):\n\n def setUp(self):\n session.current_session = session.factory()\n\n def tearDown(self):\n session.current_session = None\n\nIn plone projects you can use the ``BUILDER_LAYER`` which your testing layer should base on. So the the session management is handled by the ``BUILDER_LAYER``:\n\n.. code:: python\n\n from ftw.builder.testing import BUILDER_LAYER\n\n class MyPackageLayer(PloneSandboxLayer):\n\n defaultBases = (PLONE_FIXTURE, BUILDER_LAYER)\n\nUse the builder for creating objects in your tests:\n\n.. code:: python\n\n\n from ftw.builder import Builder\n from ftw.builder import create\n from my.package.testing import MY_PACKAGE_INTEGRATION_TESTING\n from unittest2 import TestCase\n\n class TestMyFeature(TestCase)\n\n layer = MY_PACKAGE_INTEGRATION_TESTING\n\n def test_folder_is_well_titled(self):\n folder = create(Builder('folder')\n .titled('My Folder')\n .in_state('published'))\n\n self.assertEquals('My Folder', folder.Title())\n\n\nSession\n~~~~~~~\n\nThe ``BuilderSession`` keeps configuration for multiple builders. It is set up\nand destroyed by the ``BUILDER_LAYER`` and can be configured or replaced by a\ncustom session with ``set_builder_session_factory``.\n\nAuto commit\n+++++++++++\n\nWhen having a functional testing layer (``plone.app.testing.FunctionalTesting``)\nand doing browser tests it is necessary that the new objects are committed in\nthe ZODB. When using a ``IntegrationTesting`` on the other hand it is essential\nthat nothing is comitted, since this would break test isolation.\n\nThe session provides the ``auto_commit`` option (dislabed by default), which\ncommits to the ZODB after creating an object. Since it is disabled by default\nyou need to enable it in functional test cases.\n\nA default session factory ``functional_session_factory`` that enables the\nauto-commit feature is provided:\n\n.. code:: python\n\n def functional_session_factory():\n sess = BuilderSession()\n sess.auto_commit = True\n return sess\n\n\nYou can use ``set_builder_session_factory`` to replace the default session\nfactory in functional tests. Make sure to also base your fixture on the\n``BUILDER_LAYER`` fixture:\n\n.. code:: python\n\n from ftw.builder.session import BuilderSession\n from ftw.builder.testing import BUILDER_LAYER\n from ftw.builder.testing import functional_session_factory\n from ftw.builder.testing import set_builder_session_factory\n from plone.app.testing import FunctionalTesting\n from plone.app.testing import IntegrationTesting\n from plone.app.testing import PLONE_FIXTURE\n from plone.app.testing import PloneSandboxLayer\n\n\n class MyPackageLayer(PloneSandboxLayer):\n defaultBases = (PLONE_FIXTURE, BUILDER_LAYER)\n\n MY_PACKAGE_FIXTURE = MyPackageLayer()\n\n MY_PACKAGE_INTEGRATION_TESTING = IntegrationTesting(\n bases=(MY_PACKAGE_FIXTURE, ),\n name=\"MyPackage:Integration\")\n\n MY_PACKAGE_FUNCTIONAL_TESTING = FunctionalTesting(\n bases=(MY_PACKAGE_FIXTURE,\n set_builder_session_factory(functional_session_factory)),\n name=\"MyPackage:Integration\")\n\n\n\nPlone object builders\n~~~~~~~~~~~~~~~~~~~~~\n\nFor creating Plone objects (Archetypes or Dexterity) there are some methods for\nsetting basic options:\n\n- ``within(container)`` - tell the builder where to create the object\n- ``titled(title)`` - name the object\n- ``having(field=value)`` - set the value of any field on the object\n- ``in_state(review_state)`` - set the object into any review state of the workflow\n configured for this type\n- ``providing(interface1, interface2, ...)`` - let the object provide interfaces\n- ``with_property(name, value, value_type='string')`` - set a property\n\n\n\nDefault builders\n~~~~~~~~~~~~~~~~\n\nThe ``ftw.builder`` ships with some builders for some default Plone\ncontent types, but the idea is that you can easily craft your own builders for\nyour types or extend existing builders.\n\nThe built-in builders are:\n\n- ``folder`` - creates an folder\n- ``page`` (or ``document``) - creates an page (alias Document)\n- ``file`` - creates a File\n- ``image`` - creates an Image\n- ``collection`` (or ``topic``) - creates a collection\n\nThere are two builder implementations, an Archetypes (Plone < 5) and a\nDexterity (Plone >= 5) implementation.\nWhen using ``plone.app.contenttypes`` with Plone 4, you may want to switch\nthe builders to dexterity:\n\n.. code:: python\n\n from ftw.builder.content import at_content_builders_registered\n from ftw.builder.content import dx_content_builders_registered\n from ftw.builder.content import register_at_content_builders\n from ftw.builder.content import register_dx_content_builders\n\n\n # permanently\n register_dx_content_builders(force=True)\n\n # temporary\n with dx_content_builders_registered():\n # do stuff\n\n\nAttaching files\n+++++++++++++++\n\nThe default Archetypes file builder let's you attach a file or create the file\nwith dummy content. The archetypes image builder provides a real image (1x1 px GIF):\n\n.. code:: python\n\n file1 = create(Builder('file')\n .with_dummy_content())\n\n file2 = create(Builder('file')\n .attach_file_containing('File content', name='filename.pdf')\n\n image1 = create(Builder('image')\n .with_dummy_content())\n\n\nUsers builder\n+++++++++++++\n\nThere is a \"user\" builder registered by default.\n\nBy default the user is named John Doe:\n\n.. code:: python\n\n john = create(Builder('user'))\n john.getId() == \"john.doe\"\n john.getProperty('fullname') == \"Doe John\"\n john.getProperty('email') == \"john@doe.com\"\n john.getRoles() == ['Member', 'Authenticated']\n\nChanging the name of the user changes also the userid and the email address.\nYou can also configure all the other necessary things:\n\n.. code:: python\n\n folder = create(Builder('folder'))\n hugo = create(Builder('user')\n .named('Hugo', 'Boss')\n .with_roles('Contributor')\n .with_roles('Editor', on=folder))\n\n hugo.getId() == 'hugo.boss'\n hugo.getProperty('fullname') == 'Boss Hugo'\n hugo.getProperty('email') == 'hugo@boss.com'\n hugo.getRoles() == ['Contributor', 'Authenticated']\n hugo.getRolesInContext(folder) == ['Contributor', 'Authenticated', 'Editor']\n\n\nGroups builder\n++++++++++++++\n\nThe \"group\" bilder helps you create groups:\n\n.. code:: python\n\n folder = create(Builder('folder'))\n user = create(Builder('user'))\n group = create(Builder('group')\n .titled('Administrators')\n .with_roles('Site Administrator')\n .with_roles('Editor', on=folder)\n .with_members(user))\n\n\n\nCreating new builders\n~~~~~~~~~~~~~~~~~~~~~\n\nThe idea is that you create your own builders for your application.\nThis might be builders creating a single Plone object (Archetypes or Dexterity)\nor builders creating a set of objects using other builders.\n\n\nCreating python builders\n++++++++++++++++++++++++\n\nDefine a simpe builder class for your python object and register them in the builder registry\n\n.. code:: python\n\n class PersonBuilder(object):\n\n def __init__(self, session):\n self.session = session\n self.children_names = []\n self.arguments = {}\n\n def of_age(self):\n self.arguments['age'] = 18\n return self\n\n def with_children(self, children_names):\n self.children_names = children_names\n return self\n\n def having(self, **kwargs):\n self.arguments.update(kwargs)\n return self\n\n def create(self, **kwargs):\n person = Person(\n self.arguments.get('name'),\n self.arguments.get('age'))\n\n for name in self.children_names:\n person.add_child(\n create(Builder('person').having(name=name, age=5))\n )\n\n return person\n\n builder_registry.register('person', PersonBuilder)\n\n\nCreating Archetypes builders\n++++++++++++++++++++++++++++\n\nUse the ``ArchetypesBuilder`` base class for creating new Archetypes builders.\nSet the ``portal_type`` and your own methods.\n\n.. code:: python\n\n from ftw.builder.archetypes import ArchetypesBuilder\n from ftw.builder import builder_registry\n\n class NewsBuilder(ArchetypesBuilder):\n portal_type = 'News Item'\n\n def containing(self, text):\n self.arguments['text'] = text\n return self\n\n builder_registry.register('news', NewsBuilder)\n\n\nCreating Dexterity builders\n+++++++++++++++++++++++++++\n\nUse the ``DexterityBuilder`` base class for creating new Dexterity builders.\nSet the ``portal_type`` and your own methods.\n\n.. code:: python\n\n from ftw.builder.dexterity import DexterityBuilder\n from ftw.builder import builder_registry\n\n class DocumentBuilder(DexterityBuilder):\n portal_type = 'dexterity.document'\n\n def with_dummy_content(self):\n self.arguments[\"file\"] = NamedBlobFile(data='Test data', filename='test.doc')\n return self\n\n\nEvents\n++++++\n\nYou can do things before and after creating the object:\n\n.. code:: python\n\n class MyBuilder(ArchetypesBuilder):\n\n def before_create(self):\n super(NewsBuilder, self).before_create()\n do_something()\n\n def after_create(self):\n do_something()\n super(NewsBuilder, self).after_create()\n\n\nOverriding existing builders\n++++++++++++++++++++++++++++\n\nSometimes it is necessary to override an existing builder.\nFor re-registering an existing builder you can use\nthe ``force`` flag:\n\n.. code:: python\n\n builder_registry.register('file', CustomFileBuilder, force=True)\n\n\nTicking frozen clock forward on create\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWith ``ftw.testing`` it is possible to\n`freeze the time `_.\n\nWhen freezing the time and creating multiple objects, they will all end up with\nthe same creation date. This can cause an inconsistent sorting order.\n\nIn order to solve this problem, ``ftw.builder`` provides a ``ticking_creator``,\nwhich moves the clock forward every time an object is created.\nThis means we have distinct, consistent creation dates.\n\nUsage example:\n\n.. code:: python\n\n from datetime import datetime\n from ftw.builder import Builder\n from ftw.builder import ticking_creator\n from ftw.testing import freeze\n\n with freeze(datetime(2010, 1, 1)) as clock:\n create = ticking_creator(clock, days=1)\n self.assertEquals(DateTime(2010, 1, 1),\n create(Builder('folder')).created())\n self.assertEquals(DateTime(2010, 1, 2),\n create(Builder('folder')).created())\n self.assertEquals(DateTime(2010, 1, 3),\n create(Builder('folder')).created())\n\n\nIt is convenient to install the ticking creator globally, so if builder\ncreates objects with another builder, it also ticks the clock for the\nnested builder call.\nThis can be achieved by using the ticking creator as context manager:\n\n.. code:: python\n\n from datetime import datetime\n from ftw.builder import Builder\n from ftw.builder import create\n from ftw.builder import ticking_creator\n from ftw.testing import freeze\n\n with freeze(datetime(2010, 1, 1)) as clock:\n with ticking_creator(clock, days=1):\n self.assertEquals(DateTime(2010, 1, 1),\n create(Builder('folder')).created())\n self.assertEquals(DateTime(2010, 1, 2),\n create(Builder('folder')).created())\n self.assertEquals(DateTime(2010, 1, 3),\n create(Builder('folder')).created())\n\n\n\nOther builders\n--------------\n\nPython package builder\n~~~~~~~~~~~~~~~~~~~~~~\n\nThe Python package builder builds a python package on the file system.\n\n- creates a setup.py\n- namespace packages are supported\n- builds the egg-info\n- creates a configure.zcml on demand\n\nExample:\n\n.. code:: python\n\n >>> import tempfile\n >>> tempdir = tempfile.mkdtemp()\n\n >>> package = create(Builder('python package')\n ... .at_path(tempdir)\n ... .named('my.package')\n ...\n ... .with_root_directory('docs')\n ... .with_root_file('docs/HISTORY.txt', 'CHANGELOG...')\n ... .with_file('resources/print.css', 'body {}', makedirs=True)\n ...\n ... .with_subpackage(Builder('subpackage')\n ... .named('browser')))\n >>>\n >>> with package.imported() as module:\n ... print module\n ...\n \n\nIt is also possible to create / load ZCML, all you need is a stacked configuration context.\nPlone's testing layers provide a configuration context, but be aware that the component\nregistry is not isolated.\nYou may want to isolate the component registry with\n`plone.testing.zca.pushGlobalRegistry `_.\n\n.. code:: python\n\n package = create(\n Builder('python package')\n .named('the.package')\n .at_path(self.layer['temp_directory'])\n\n .with_subpackage(\n Builder('subpackage')\n .named('browser')\n\n .with_file('hello_world.pt', '\"Hello World\"')\n .with_zcml_node('browser:page',\n **{'name': 'hello-world.json',\n 'template': 'hello_world.pt',\n 'permission': 'zope2.View',\n 'for': '*'})))\n\n with package.zcml_loaded(self.layer['configurationContext']):\n self.assertEqual('\"Hello World\"',\n self.layer['portal'].restrictedTraverse('hello-world.json')())\n\n\nGeneric Setup profile builder\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe \"genericsetup profile\" builder helps building a profile within a python package:\n\n.. code:: python\n\n create(Builder('python package')\n .named('the.package')\n .at_path(self.layer['temp_directory'])\n\n .with_profile(Builder('genericsetup profile')\n .with_fs_version('3109')\n .with_dependencies('collective.foo:default')\n .with_file('types/MyType.xml', '',\n makedirs=True)))\n\n\nPlone upgrade step builder\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBuilds a Generic Setup upgrade step for a package:\n\n.. code:: python\n\n create(Builder('python package')\n .named('the.package')\n .at_path(self.layer['temp_directory'])\n\n .with_profile(Builder('genericsetup profile')\n .with_upgrade(Builder('plone upgrade step')\n .upgrading('1000', '1001')\n .titled('Add some actions...')\n .with_description('Some details...'))))\n\n\n\nZCML file builder\n~~~~~~~~~~~~~~~~~\n\nThe ZCML builder builds a ZCML file:\n\n.. code:: python\n\n create(Builder('zcml')\n .at_path('/path/to/my/package/configure.zcml')\n .with_i18n_domain('my.package')\n\n .include('.browser')\n .include('Products.GenericSetup', file='meta.zcml')\n .include(file='profiles.zcml')\n\n .with_node('i18n:registerTranslations', directory='locales'))\n\n\nPortlet builder\n~~~~~~~~~~~~~~~\n\nThe ``ftw.builder`` ships with a few builders for Plone portlets, but the\nidea is that you can easily craft your own builders for your portlets or\nextend existing builders.\n\nExample:\n\n.. code:: python\n\n from ftw.builder import builder_registry\n from ftw.builder.portlets import PlonePortletBuilder\n from my.package.portlets import my_portlet\n\n class MyPortletBuilder(PlonePortletBuilder):\n assignment_class = my_portlet.Assignment\n\n builder_registry.register('my portlet', MyPortletBuilder)\n\n\nThe built-in builders are:\n\n- ``static portlet`` - creates a static portlet\n- ``navigation portlet`` - creates a navigation portlet\n\n\nDevelopment / Tests\n-------------------\n\n.. code:: bash\n\n $ git clone https://github.com/4teamwork/ftw.builder.git\n $ cd ftw.builder\n $ ln -s development.cfg buildout.cfg\n $ python2.7 bootstrap.py\n $ ./bin/buildout\n $ ./bin/test\n\n\nLinks\n-----\n\n- Github: https://github.com/4teamwork/ftw.builder\n- Issues: https://github.com/4teamwork/ftw.builder/issues\n- Pypi: http://pypi.python.org/pypi/ftw.builder\n- Continuous integration: https://jenkins.4teamwork.ch/search?q=ftw.builder\n\n\nCopyright\n---------\n\nThis package is copyright by `4teamwork `_.\n\n``ftw.builder`` is licensed under GNU General Public License, version 2.\n\nChangelog\n=========\n\n\n1.11.1 (2017-06-20)\n-------------------\n\n- Fix typos. [mbaechtold]\n\n\n1.11.0 (2017-06-16)\n-------------------\n\n- Make ticking creator installable globally by using as context manager. [jone]\n- Fix test: test_object_providing_interface_updates_catalog: Asks catalog instead of index (query lazyness) [tarnap]\n- Fix dexterity image builder [tarnap]\n\n\n1.10.0 (2017-03-01)\n-------------------\n\n- Add \"ticking_creator\", ticking a frozen clock. [jone]\n\n\n1.9.0 (2016-09-19)\n------------------\n\n- Add \".with_property\" method to content builders. [jone]\n\n\n1.8.1 (2016-06-30)\n------------------\n\n- Fix plone.app.dexterity dependency in order to better support Plone 4.2. [jone]\n\n\n1.8.0 (2016-06-29)\n------------------\n\n- Add content manager for switching to AT / DX content builders. [jone]\n\n- Require dexterity. [jone]\n\n\n1.7.5 (2016-05-26)\n------------------\n\n- DX: Bind zope.schema fields when determining default values in order to\n have a context (i.e. container) to pass to an IContextAwareDefaultFactory.\n [lgraf]\n\n\n1.7.4 (2016-03-30)\n------------------\n\n- Fix setting values for dexterity-readonly fields.\n [elioschmutz]\n\n- Fix encoding problem when creating AT blobs. [jone]\n\n\n1.7.3 (2015-12-11)\n------------------\n\n- UserBuilder: add method to create a user within specified groups.\n [deiferni]\n\n\n1.7.2 (2015-09-30)\n------------------\n\n- DX-Builder: Initialize attributes only with set_field_values.\n No longer pass all arguments to createContent to avoid setting fields that\n are stored in annotations as attributes as well.\n [deiferni]\n\n\n1.7.1 (2015-08-20)\n------------------\n\n- Add conditional import for Relationvalues since we don't always have z3c.relation.\n [tschanzt]\n\n\n1.7.0 (2015-08-20)\n------------------\n\n- Automatically create relation-values from plone content-types while setting field-values.\n [deiferni]\n\n- Add support for building portlets.\n [mbaechtold]\n\n\n1.6.3 (2015-05-28)\n------------------\n\n- Genericsetup builder: fix error when creating same folder multiple times.\n [jone]\n\n\n1.6.2 (2015-05-20)\n------------------\n\n- Package builder: make package version configurable.\n [jone]\n\n\n1.6.1 (2015-05-20)\n------------------\n\n- Package builder: update pkg_resources working set when loading package.\n [jone]\n\n- Add creation date setter to builder.\n [mbaechtold]\n\n\n1.6.0 (2014-12-31)\n------------------\n\n- Add more default builders:\n\n - a \"zcml\" builder for creating ZCML files\n - a \"python package\" builder for creating python package on the file system\n - a \"namespace package\" builder, used internally by the \"python package\" builder\n - a \"subpackage\" builder for extending a python package with nested packages\n - a \"genericsetup profile\" builder\n - a \"plone upgrade step\" builder for building Generic Setup upgrade steps\n\n [jone]\n\n\n1.5.2 (2014-12-06)\n------------------\n\n- File builder: fix default filename encoding for AT.\n This was a regression in 1.5.0, where filenames were changed to unicode\n because of the consolidation of Archetypes and Dexterity builders.\n [jone]\n\n\n1.5.1 (2014-12-03)\n------------------\n\n- Fix NamedBlobFile import issue for Plone <= 4.2 where blobs are optional.\n [jone]\n\n\n1.5.0 (2014-12-03)\n------------------\n\n- Restore Plone 4.1 compatibility by making any DX imports conditional.\n [lgraf]\n\n- Plone 5 support: default content builders are switched to the dexterity implementation\n by default for Plone >= 5.\n The builder classes were moved from ``archetypes`` module to ``content`` module.\n [jone]\n\n\n1.4.0 (2014-09-04)\n------------------\n\n- Implement collection builder.\n [jone]\n\n- Fixed default value setter for different \"owners\" field.\n [phgross]\n\n\n1.3.4 (2014-08-29)\n------------------\n\n- DxBuilder: Fix encoding problem when filling default value for \"owners\" field.\n [jone]\n\n\n1.3.3 (2014-06-05)\n------------------\n\n- DxBuilder: Fix check if field is present (to determine if default values should be set).\n [lgraf]\n\n- DxBuilder: Make sure default values are set before adding content to container.\n [lgraf]\n\n\n1.3.2 (2014-05-29)\n------------------\n\n- Update object_provides in catalog when using provides().\n [jone]\n\n\n1.3.1 (2014-03-26)\n------------------\n\n- Provide a real image (1x1 px GIF) for the Archetypes ImageBuilder.\n [mathias.leimgruber]\n\n\n1.3.0 (2014-03-25)\n------------------\n\n- Implement ATImage builder.\n [jone]\n\n- Reindex object security after setting local roles for a principal.\n [mathias.leimgruber]\n\n- Support \"on\" keyword argument for with_roles method in group builder.\n [mathias.leimgruber]\n\n\n1.2.0 (2014-01-31)\n------------------\n\n- Add `providing()` method to Plone builder,\n letting the object provide interfaces.\n [jone]\n\n- Don't use IDNormalizer for Mail. It handles Umlauts weird.\n [tschanzt]\n\n\n1.1.0 (2013-09-13)\n------------------\n\n- Add groups builder.\n [jone]\n\n- Add users builder.\n [jone]\n\n- Added modification date setter for PloneObject Builders.\n [phgross]\n\n\n1.0.0 (2013-08-12)\n------------------\n\n- Added dexterity support.\n [phgross]\n\n- Initial implementation\n [jone]", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/4teamwork/ftw.builder", "keywords": "ftw builder plone", "license": "GPL2", "maintainer": "", "maintainer_email": "", "name": "ftw.builder", "package_url": "https://pypi.org/project/ftw.builder/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/ftw.builder/", "project_urls": { "Homepage": "https://github.com/4teamwork/ftw.builder" }, "release_url": "https://pypi.org/project/ftw.builder/1.11.1/", "requires_dist": null, "requires_python": "", "summary": "Builder pattern for creating Plone objects in tests", "version": "1.11.1" }, "last_serial": 5823524, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "d01433c6f34d788efea055dd2b91c8b1", "sha256": "8da61678b070ef4cb5b9e3786c13b4be6ec0f063f71dcc6605b8430d51aa8348" }, "downloads": -1, "filename": "ftw.builder-1.0.0.zip", "has_sig": false, "md5_digest": "d01433c6f34d788efea055dd2b91c8b1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28997, "upload_time": "2013-08-12T13:20:07", "url": "https://files.pythonhosted.org/packages/19/fa/ebf2f30f1988124d956e6033a91a90c36382c0f20c3839df8bb8758a4bc2/ftw.builder-1.0.0.zip" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "106678e986a2be399c58b2b807ad826f", "sha256": "12603405bf0d1c6c7f22bcc14c4c4e7a17b5d06f816944ee580570507dd61a80" }, "downloads": -1, "filename": "ftw.builder-1.1.0.zip", "has_sig": false, "md5_digest": "106678e986a2be399c58b2b807ad826f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34531, "upload_time": "2013-09-13T14:34:53", "url": "https://files.pythonhosted.org/packages/4a/03/2b6b6e054b7205195b35a0bfb16df0a23bcc083eef9b22a80b6703558ba6/ftw.builder-1.1.0.zip" } ], "1.10.0": [ { "comment_text": "", "digests": { "md5": "ee8b3dfbe45e61973af9fb4f1a83504e", "sha256": "47301f5908f4ce8283dee703204d4db65448c05d20a39f67423d6e9b6e4ee9a1" }, "downloads": -1, "filename": "ftw.builder-1.10.0.tar.gz", "has_sig": false, "md5_digest": "ee8b3dfbe45e61973af9fb4f1a83504e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49823, "upload_time": "2017-03-01T08:55:26", "url": "https://files.pythonhosted.org/packages/68/32/26c673f71181782994ec7eff45644969d313ab0186f314c27da417921af0/ftw.builder-1.10.0.tar.gz" } ], "1.11.0": [ { "comment_text": "", "digests": { "md5": "0d8b7c8e0184d141b7db0577c57af1de", "sha256": "2a788508116c38d2e1c790a9377b115bd7d8aefd066647e7d1b448ec03d5780a" }, "downloads": -1, "filename": "ftw.builder-1.11.0.tar.gz", "has_sig": false, "md5_digest": "0d8b7c8e0184d141b7db0577c57af1de", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 51034, "upload_time": "2017-06-16T08:09:18", "url": "https://files.pythonhosted.org/packages/37/80/73066034607cf2e410de03e981328300869e86dff10f8a7e7a81326f5acd/ftw.builder-1.11.0.tar.gz" } ], "1.11.1": [ { "comment_text": "", "digests": { "md5": "b4d04f15b93fff07af4b52b42042bdb9", "sha256": "cd6c2aaec4a8f9b114acabbcdad85cb4ea42247b3759fb3145d9a339d0652061" }, "downloads": -1, "filename": "ftw.builder-1.11.1.tar.gz", "has_sig": false, "md5_digest": "b4d04f15b93fff07af4b52b42042bdb9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 51178, "upload_time": "2017-06-20T12:15:23", "url": "https://files.pythonhosted.org/packages/a5/eb/7dda0c5469e313f9f56bfee8694daa57b86d218815874008ed11e363b486/ftw.builder-1.11.1.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "c9e22782baa6a82c3adc1a95b234f49f", "sha256": "742cbe9ec86c601d7e99eb8e9e881397accc416317f06bbbe30e2094fb6fdefc" }, "downloads": -1, "filename": "ftw.builder-1.2.0.zip", "has_sig": false, "md5_digest": "c9e22782baa6a82c3adc1a95b234f49f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35461, "upload_time": "2014-01-31T09:05:39", "url": "https://files.pythonhosted.org/packages/f5/29/e6defc5f2df31fe7bf7e0a8615ec26b9f85f388f955f2d785e17ac7d5e83/ftw.builder-1.2.0.zip" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "182775fa5614fb0de127aadfdacf1cc4", "sha256": "7302e19a4f9d6da3cfc15b6c669a1f2d83228b8e6a44285eb59781b9bdda5871" }, "downloads": -1, "filename": "ftw.builder-1.3.0.zip", "has_sig": false, "md5_digest": "182775fa5614fb0de127aadfdacf1cc4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36582, "upload_time": "2014-03-25T12:36:25", "url": "https://files.pythonhosted.org/packages/22/96/733da8a377c03b12dff7eb777333aca2bd53c5c8ea069a800d7381d09919/ftw.builder-1.3.0.zip" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "34ef85aa6dd38ff6e1abc440533f38cc", "sha256": "4c1686ffaeab0ad6907e57d9510cc6a5de3f5d824014672b90919586d19eb8ea" }, "downloads": -1, "filename": "ftw.builder-1.3.1.zip", "has_sig": false, "md5_digest": "34ef85aa6dd38ff6e1abc440533f38cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37066, "upload_time": "2014-03-26T13:41:03", "url": "https://files.pythonhosted.org/packages/8c/b0/ec36b41f216b1092b3b8b2e51bf0ce38172508aeb06930e5676b2aa1e38d/ftw.builder-1.3.1.zip" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "94dffcb1d655d70c4fc34315f8797442", "sha256": "6f12c299537d28add59d8880738507a4a46eb6ff0a21ca0243d0bee1f88ab112" }, "downloads": -1, "filename": "ftw.builder-1.3.2.zip", "has_sig": false, "md5_digest": "94dffcb1d655d70c4fc34315f8797442", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37354, "upload_time": "2014-05-29T09:09:09", "url": "https://files.pythonhosted.org/packages/b5/a6/b5a95452892122c546618ab15410e55fdcfede00e36a00483a1736934ee4/ftw.builder-1.3.2.zip" } ], "1.3.3": [ { "comment_text": "", "digests": { "md5": "f3cf76c34ef3cfda36a1fc911bf4167b", "sha256": "e24fbf729e98fa1024c1e95dddacb7d005423b4932ffc1d2a6ae8a4152f0a16b" }, "downloads": -1, "filename": "ftw.builder-1.3.3.zip", "has_sig": false, "md5_digest": "f3cf76c34ef3cfda36a1fc911bf4167b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37824, "upload_time": "2014-06-05T09:53:47", "url": "https://files.pythonhosted.org/packages/7f/9c/95e7115139522e73310b84bbce700a0e390a539eb61b3705f629e8b1736b/ftw.builder-1.3.3.zip" } ], "1.3.4": [ { "comment_text": "", "digests": { "md5": "660eec2180a35e0c7886849b7bae5d3b", "sha256": "8df089952d7669cf6519449bc4440433ea430ea75be7614e687e312e30550aae" }, "downloads": -1, "filename": "ftw.builder-1.3.4.zip", "has_sig": false, "md5_digest": "660eec2180a35e0c7886849b7bae5d3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38062, "upload_time": "2014-08-29T14:40:35", "url": "https://files.pythonhosted.org/packages/62/0c/2a80df028eb832591256a9fc37e1be9910c4a195f82886c5bac967eb0f62/ftw.builder-1.3.4.zip" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "83bc21d3f5ef707c50cb7330b2e924c1", "sha256": "d96ae23b0c87dfb1a9eaeacecaf85e02a1e84c204f11bb130d371c0c02644209" }, "downloads": -1, "filename": "ftw.builder-1.4.0.zip", "has_sig": false, "md5_digest": "83bc21d3f5ef707c50cb7330b2e924c1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39045, "upload_time": "2014-09-04T07:22:38", "url": "https://files.pythonhosted.org/packages/79/a1/e9fa3fb95071b761a4ec404764f1558563f6e699261bc8e1011ee83bbd0a/ftw.builder-1.4.0.zip" } ], "1.5.0": [ { "comment_text": "", "digests": { "md5": "5011f5fa49ee68d83682ca0417f640c6", "sha256": "127bc4d7a792a486bdc90b46d81c8d6b69e541fba649757f5151a5a1dc77f314" }, "downloads": -1, "filename": "ftw.builder-1.5.0.zip", "has_sig": false, "md5_digest": "5011f5fa49ee68d83682ca0417f640c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40713, "upload_time": "2014-12-03T20:48:36", "url": "https://files.pythonhosted.org/packages/50/78/8afe07a89d326e1a72d7a98bc250510b81597ad0db43f3d1115d61ef0cb9/ftw.builder-1.5.0.zip" } ], "1.5.1": [ { "comment_text": "", "digests": { "md5": "a413e58c5c405eca46859fb81c929fc5", "sha256": "500d28e0c7164affedc0ef2267101a722f557c5877632ef391c05532d6fe878f" }, "downloads": -1, "filename": "ftw.builder-1.5.1.zip", "has_sig": false, "md5_digest": "a413e58c5c405eca46859fb81c929fc5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40857, "upload_time": "2014-12-03T21:06:27", "url": "https://files.pythonhosted.org/packages/fa/af/d7394098ff7cfbcd7fe2673eab56fee9974d91eb49a76e01cf02b7581dbe/ftw.builder-1.5.1.zip" } ], "1.5.2": [ { "comment_text": "", "digests": { "md5": "5006f9f3f2d72e1fa59349d683776f17", "sha256": "d7d6e57a7921b71404665d6f3f9b6cf19355acf257cd87b43bda3ef8b116a977" }, "downloads": -1, "filename": "ftw.builder-1.5.2.zip", "has_sig": false, "md5_digest": "5006f9f3f2d72e1fa59349d683776f17", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 41121, "upload_time": "2014-12-06T20:57:44", "url": "https://files.pythonhosted.org/packages/d1/74/cf32f4fde1a0362ff5234adeffafbe974694ed99d616c372b7ed7910330f/ftw.builder-1.5.2.zip" } ], "1.6.0": [ { "comment_text": "", "digests": { "md5": "48cb528a53c51ce6878bcfda5bf215a1", "sha256": "15d1fc771734d32c3fd8bbf10e7ab8514ebfc84beaa163a78e99d995677bac93" }, "downloads": -1, "filename": "ftw.builder-1.6.0.zip", "has_sig": false, "md5_digest": "48cb528a53c51ce6878bcfda5bf215a1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 61150, "upload_time": "2014-12-31T11:42:45", "url": "https://files.pythonhosted.org/packages/35/60/d371d0c0c1a20e5d408118a20156542bf91a500c87b222b66d4267595387/ftw.builder-1.6.0.zip" } ], "1.6.1": [ { "comment_text": "", "digests": { "md5": "13fe9836979d851a82fb6a151f76f553", "sha256": "15d506ee644e4fb1e463fccb650d6de8c83ff05e771ec6f413e3aa96bf5d88ff" }, "downloads": -1, "filename": "ftw.builder-1.6.1.zip", "has_sig": false, "md5_digest": "13fe9836979d851a82fb6a151f76f553", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 61438, "upload_time": "2015-05-20T14:41:38", "url": "https://files.pythonhosted.org/packages/bd/bb/43d0f6feff358b101858d63fd5e35571a95b9746f9275a74dc9d0888739e/ftw.builder-1.6.1.zip" } ], "1.6.2": [ { "comment_text": "", "digests": { "md5": "f3d33ee87e698a594dbb99dfbba0e238", "sha256": "12e15f571c7919e9254477e85cd6fb2d7e10095500cde76bb00f1cc82878896e" }, "downloads": -1, "filename": "ftw.builder-1.6.2.zip", "has_sig": false, "md5_digest": "f3d33ee87e698a594dbb99dfbba0e238", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 61590, "upload_time": "2015-05-20T14:55:56", "url": "https://files.pythonhosted.org/packages/9c/b6/d5a8177e39346f4ab5b9d22d6a840cc1ceb208117229bbbc832ba65d5594/ftw.builder-1.6.2.zip" } ], "1.6.3": [ { "comment_text": "", "digests": { "md5": "779fdff66188ba0e978d7b78f2de5222", "sha256": "3e37fdc07927894e96fc824128bf8581c32fed3872e4b436b2d5a59c79c911be" }, "downloads": -1, "filename": "ftw.builder-1.6.3.zip", "has_sig": false, "md5_digest": "779fdff66188ba0e978d7b78f2de5222", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 61697, "upload_time": "2015-05-28T11:44:36", "url": "https://files.pythonhosted.org/packages/45/8e/573538f4c104281f918499ba4c734239b5d5e31061b74e8dacca168b46c0/ftw.builder-1.6.3.zip" } ], "1.7.0": [ { "comment_text": "", "digests": { "md5": "775a5b733f44104259c431c1d0769010", "sha256": "40d8956b958e14a460eb7369fb21b423118a2c1f67f8fb041a36f9e620fa7098" }, "downloads": -1, "filename": "ftw.builder-1.7.0.tar.gz", "has_sig": false, "md5_digest": "775a5b733f44104259c431c1d0769010", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40267, "upload_time": "2015-08-20T11:31:17", "url": "https://files.pythonhosted.org/packages/3c/f5/1bdb8d639633b56390fd561602e52d1552d7ea7ae7c0b05582326dea2fdc/ftw.builder-1.7.0.tar.gz" } ], "1.7.1": [ { "comment_text": "", "digests": { "md5": "5ec259bc837d4dc3851d22cef92596bb", "sha256": "7beba7a3a351cfd759c5a1f166477ab6d7d5a3e63313a12a811ca37045796627" }, "downloads": -1, "filename": "ftw.builder-1.7.1.zip", "has_sig": false, "md5_digest": "5ec259bc837d4dc3851d22cef92596bb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 64903, "upload_time": "2015-08-20T13:19:16", "url": "https://files.pythonhosted.org/packages/d8/ed/01d227e3999e67cc1c1db0ea1109b7c7424b5bf68793108aa6f96c63b27b/ftw.builder-1.7.1.zip" } ], "1.7.2": [ { "comment_text": "", "digests": { "md5": "7cb99375a8bbb755fa5b6807b2748471", "sha256": "6b255ac2d79389c14f9c460096303e2d94c784010dd4da8cbd7e611cc4ba3eb0" }, "downloads": -1, "filename": "ftw.builder-1.7.2.tar.gz", "has_sig": false, "md5_digest": "7cb99375a8bbb755fa5b6807b2748471", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 41454, "upload_time": "2015-09-30T14:01:41", "url": "https://files.pythonhosted.org/packages/48/9a/729542aa7c579694e630c1af3df1096cedb06c907b36c7d545227b8bbfcf/ftw.builder-1.7.2.tar.gz" } ], "1.7.3": [ { "comment_text": "", "digests": { "md5": "bb7bc6c5d100c0e03e640d469f4c94ba", "sha256": "1c2f5bb640748334036af03b2d1c93bb52f66f9b8501590b3a50fbfd9fb0335e" }, "downloads": -1, "filename": "ftw.builder-1.7.3.zip", "has_sig": false, "md5_digest": "bb7bc6c5d100c0e03e640d469f4c94ba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 66325, "upload_time": "2015-12-11T15:21:01", "url": "https://files.pythonhosted.org/packages/0a/02/a48d5413043e566bdce47ee8f5eab1867fc8876cfc4cd37bb0f31b6aec34/ftw.builder-1.7.3.zip" } ], "1.7.4": [ { "comment_text": "", "digests": { "md5": "8237c28f86be325eae7c5efa26c0723b", "sha256": "a74a106b56e9e1aefad6ee066669ccd3a14cea965e3ada67fe16fc2c50fcb32c" }, "downloads": -1, "filename": "ftw.builder-1.7.4.tar.gz", "has_sig": false, "md5_digest": "8237c28f86be325eae7c5efa26c0723b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 41820, "upload_time": "2016-03-30T08:19:30", "url": "https://files.pythonhosted.org/packages/2c/b7/b60ab830122f68527337da46a75a03382da1acef3bdaf963f6fec838e6f9/ftw.builder-1.7.4.tar.gz" } ], "1.7.5": [ { "comment_text": "", "digests": { "md5": "5ed1f32addd584f0bd9ec7f9c2e93b76", "sha256": "51584648e3fe156abc84ba1184ecba42d03212e78ee661ff199d5052060c33cc" }, "downloads": -1, "filename": "ftw.builder-1.7.5.tar.gz", "has_sig": false, "md5_digest": "5ed1f32addd584f0bd9ec7f9c2e93b76", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42188, "upload_time": "2016-05-26T12:34:38", "url": "https://files.pythonhosted.org/packages/f8/ca/1c25737f8e6226772f84a45482a51e2e63499c7fa6b37bee81746df3e713/ftw.builder-1.7.5.tar.gz" } ], "1.8.0": [ { "comment_text": "", "digests": { "md5": "2480c53d6af034636cf65bea467ee320", "sha256": "e98df79c3a847bdcd550eea617b729ddb350491579c092bbf9571e2c9721da2e" }, "downloads": -1, "filename": "ftw.builder-1.8.0.tar.gz", "has_sig": false, "md5_digest": "2480c53d6af034636cf65bea467ee320", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48104, "upload_time": "2016-06-29T15:02:33", "url": "https://files.pythonhosted.org/packages/9f/0e/2d345464efd940789068f753dbc31f96532aac431f3c17c13c4c9d506e12/ftw.builder-1.8.0.tar.gz" } ], "1.8.1": [ { "comment_text": "", "digests": { "md5": "f304fffb4a59dbe3e858707395381683", "sha256": "a21277fe0386f72ab1e12f357f561140007e124202d527136cd379211b0f2f73" }, "downloads": -1, "filename": "ftw.builder-1.8.1.tar.gz", "has_sig": false, "md5_digest": "f304fffb4a59dbe3e858707395381683", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48376, "upload_time": "2016-06-30T06:26:34", "url": "https://files.pythonhosted.org/packages/1f/2d/015c61361bff9d34030bb51bfb3d844c93b0b21838f8b0491c5bf264a5f1/ftw.builder-1.8.1.tar.gz" } ], "1.9.0": [ { "comment_text": "", "digests": { "md5": "959997b243fb5a2f10f8e9a7a7b09f6a", "sha256": "bcedb1158d5c9fc50b370da5e4987208ce467d51458525dad16b0ccbf2598c9b" }, "downloads": -1, "filename": "ftw.builder-1.9.0.tar.gz", "has_sig": false, "md5_digest": "959997b243fb5a2f10f8e9a7a7b09f6a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48673, "upload_time": "2016-09-19T09:53:00", "url": "https://files.pythonhosted.org/packages/fa/37/f566a4cecc71c42c8a002673da689319f8d5164297d7a9b98c65fcc5bf93/ftw.builder-1.9.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b4d04f15b93fff07af4b52b42042bdb9", "sha256": "cd6c2aaec4a8f9b114acabbcdad85cb4ea42247b3759fb3145d9a339d0652061" }, "downloads": -1, "filename": "ftw.builder-1.11.1.tar.gz", "has_sig": false, "md5_digest": "b4d04f15b93fff07af4b52b42042bdb9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 51178, "upload_time": "2017-06-20T12:15:23", "url": "https://files.pythonhosted.org/packages/a5/eb/7dda0c5469e313f9f56bfee8694daa57b86d218815874008ed11e363b486/ftw.builder-1.11.1.tar.gz" } ] }