{ "info": { "author": "David Daniel", "author_email": "davydany@aeroxis.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "License :: OSI Approved :: MIT License", "Operating System :: MacOS", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Unix Shell" ], "description": ".. image:: https://raw.githubusercontent.com/aeroxis/sower/master/img/sower-logo.png\n :alt: Sultan logo\n :align: right\n :width: 300px\n :scale: 50%\n\n.. image:: https://badge.fury.io/py/sower.png\n :target: https://badge.fury.io/py/sower\n\n.. image:: https://travis-ci.org/aeroxis/sower.svg?branch=master\n :target: https://travis-ci.org/aeroxis/sower\n\n.. image:: http://img.shields.io/:license-mit-blue.svg\n :alt: MIT License\n :target: http://doge.mit-license.org\n\nSower\n=====\n\n**Sower \"plants\" directories, files and symlinks on your filesystem based on a contract you tell it.**\n\n\nHow to Install\n--------------\n\n.. code:: bash\n\n $ pip install sower\n\nWhy Do You Need Sower?\n======================\n\n\nThe Problem\n-----------\n\nHave you ever been in a situation where you needed to create a large set of \nfiles, that may span multiple subdirectories? You might need to do this for\ntesting, especially if your application that you're testing is supposed to \nbe tested for how it manages a set of files based on their directory \nstructure.\n\nThe Solution - Part 1\n---------------------\n\nSower is the solution for this problem! You simply define a *contract* in\nYAML or JSON like the following:\n\n+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+\n| YAML (sower-contract.yml) + JSON (sower-contract.json) +\n+=======================================================================================+===============================================================================================+\n| | |\n| .. code:: | .. code:: |\n| | |\n| --- | { |\n| sower: | \"sower\": { |\n| plan: | \"plan\": { |\n| bin: | \"bin\": { |\n| start.sh: | \"start.sh\": { |\n| type: file | \"type\": \"file\", |\n| content: \"echo 'Starting foobar'\" | \"content\": \"echo'Startingfoobar'\" |\n| stop.sh: | }, |\n| type: file | \"stop.sh\": { |\n| content: \"echo 'Stopping foobar'\" | \"type\": \"file\", |\n| data: | \"content\": \"echo'Stoppingfoobar'\" |\n| test-data.tar.gz: | } |\n| type: file | }, |\n| content: \"!random!\" | \"data\": { |\n| size: 1Mb | \"test-data.tar.gz\": { |\n| src: | \"type\": \"file\", |\n| foobar: | \"content\": \"!random!\", |\n| __init__.py: | \"size\": \"1Mb\" |\n| type: file | } |\n| content: \"# just a comment\" | }, |\n| main.py: | \"src\": { |\n| type: file | \"foobar\": { |\n| content: > | \"__init__.py\": { |\n| import os\\n | \"type\": \"file\", |\n| print('Foo Bar: %s' % os.path.abspath('.'))\\n\\n | \"content\": \"#justacomment\" |\n| link_main.py: | }, |\n| type: symlink | \"main.py\": { |\n| target: ../foobar/main.py | \"type\": \"file\", |\n| | \"content\": \"importos\\nprint('FooBar: %s'%os.path.abspath('.')\\n\\n |\n| | }, |\n| | \"link_main.py\": { |\n| | \"type\": \"symlink\", |\n| | \"target\": \"../foobar/main.py\" |\n| | } |\n| | } |\n| | } |\n| | } |\n| | } |\n| | } |\n+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+\n\nSave the Contract to disk (choose either YAML or JSON listing from above). Now \nwe simply tell Sower where to create these files, and the path to this contract.\n\nIf we want to create files based on this contract on `/home/davydany/foobar`, we would do \nthe following:\n\nIf you chose the YAML, run the following:\n.. code:: bash\n\n $ sower sow /home/davydany/foobar /tmp/sower-contract.yml\n\nIf you chose the JSON, run the following:\n.. code:: bash\n\n $ sower sow /home/davydany/foobar /tmp/sower-contract.json\n\nThis would create the following structure:\n\n.. code:: bash\n\n /home/davydany/foobar\n \u251c\u2500\u2500 bin\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 start.sh\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 stop.sh\n \u251c\u2500\u2500 data\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 test-data.tar.gz\n \u2514\u2500\u2500 src\n \u2514\u2500\u2500 foobar\n \u251c\u2500\u2500 __init__.py\n \u251c\u2500\u2500 link_main.py -> /tmp/foobar/src/foobar/main.py\n \u2514\u2500\u2500 main.py\n\n 4 directories, 6 files\n\n\nThe Solution - Part 2\n---------------------\n\nNow, suppose you need to do this in your integration tests that use python's `unittest`. You\ncan still leverage this with the Sower API.\n\nYou would have something like this in your test's `setUp` method.\n\n.. code::\n\n import tempfile\n import unittest\n from sower.farm import perform_sow\n\n class TestMyApp(unittest.TestCase):\n\n def setUp(self):\n\n self.root = tempfile.mkdtemp('_farmer_test')\n self.contract = \"\"\"\n\n ---\n sower:\n plan:\n bin:\n start.sh:\n type: file\n content: \"echo 'Starting foobar'\"\n stop.sh:\n type: file\n content: \"echo 'Stopping foobar'\"\n data:\n test-data.tar.gz:\n type: file\n content: \"!random!\"\n size: 1Mb\n src:\n foobar:\n __init__.py:\n type: file\n content: \"# just a comment\"\n main.py:\n type: file\n content: >\n import os\\n\n print('Foo Bar: %s' % os.path.abspath('.'))\\n\\n\n link_main.py:\n type: symlink\n target: ../foobar/main.py\n \"\"\"\n perform_sow(self.contract, self.root)", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/aeroxis/sower", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "sower", "package_url": "https://pypi.org/project/sower/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/sower/", "project_urls": { "Homepage": "http://github.com/aeroxis/sower" }, "release_url": "https://pypi.org/project/sower/1.1.1/", "requires_dist": [ "PyYAML (>=3.12)", "click (>=6.7)", "simplejson (>=3.10.0)" ], "requires_python": "", "summary": "Sower \"plants\" directories, files and symlinks on your filesystem based on a contract you tell it.", "version": "1.1.1" }, "last_serial": 2868451, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "0438ef7f8159af38baa23fe0ff520530", "sha256": "725f00f7638b09c5e4495f627b099d043af14f25cfbbda8506aca14f5000d759" }, "downloads": -1, "filename": "sower-1.0.0-py2-none-any.whl", "has_sig": false, "md5_digest": "0438ef7f8159af38baa23fe0ff520530", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 7489, "upload_time": "2017-05-09T04:41:39", "url": "https://files.pythonhosted.org/packages/7b/e3/a6f1d4247ba108a8c47317af39004d7c0cb3273d1fedfca1b5f907491488/sower-1.0.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b307516c7a390f5bacb1bad685923a5e", "sha256": "1be6df2e973f839959aae84a0401ffe52925cb40d972bf40ae0aa82cf7c20686" }, "downloads": -1, "filename": "sower-1.0.0.tar.gz", "has_sig": false, "md5_digest": "b307516c7a390f5bacb1bad685923a5e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4977, "upload_time": "2017-05-09T04:46:47", "url": "https://files.pythonhosted.org/packages/61/93/015d47de04f9f78ea90ccea47cc506bb523c5bc83a7436d16020ee17df6b/sower-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "bc8c68b33a6ffc39c0a55d7618a1009b", "sha256": "265cd0318c74713a54e6d4757f0c9131bf52538be9a1e475f34101773fbd11ff" }, "downloads": -1, "filename": "sower-1.0.1.tar.gz", "has_sig": false, "md5_digest": "bc8c68b33a6ffc39c0a55d7618a1009b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5055, "upload_time": "2017-05-09T04:50:32", "url": "https://files.pythonhosted.org/packages/b3/60/6529ff4c7ba0c8b65cc99f5757de4662a3570612c70131b6a1f4fa32c194/sower-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "671734b7336a326475a797c14b4ec312", "sha256": "73d31bf495e665245f1744a898572a12a54f8cd11153172389fe2a7f8402cf5b" }, "downloads": -1, "filename": "sower-1.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "671734b7336a326475a797c14b4ec312", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 7550, "upload_time": "2017-05-09T04:55:20", "url": "https://files.pythonhosted.org/packages/0c/07/d412db600a740ede4c3f5689160903a16d4a24edf7d836d93073757fd0b6/sower-1.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5d86418d3f5b3aaa758e8ac87c9bc058", "sha256": "f466296dc9d0dee4a1171986e264c968f1a7308924033eca13daced29dac0cdf" }, "downloads": -1, "filename": "sower-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "5d86418d3f5b3aaa758e8ac87c9bc058", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7545, "upload_time": "2017-05-09T04:55:17", "url": "https://files.pythonhosted.org/packages/2d/ca/bf04d4f924df5b6e18a4c5a54252d68aff5802739092bb8a6d1724043027/sower-1.0.2-py3-none-any.whl" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "45ac92c0d7e8f9699baefc9b694bce38", "sha256": "01154cc8dd4dc34adda5b8410969a87b486020040a61db82a0ebf21a7e8d7274" }, "downloads": -1, "filename": "sower-1.0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "45ac92c0d7e8f9699baefc9b694bce38", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 7968, "upload_time": "2017-05-09T05:19:11", "url": "https://files.pythonhosted.org/packages/be/28/cf847a5c0febbd62842b3624f60b0435887d70c4fc63756313545999e695/sower-1.0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e2440cc0c8854d0c98ad2bda6ea5ac5b", "sha256": "95d7af3df0f183ec91f9fe314b1715b58e2a15b3c8ca9dcecbb170362c5171d8" }, "downloads": -1, "filename": "sower-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "e2440cc0c8854d0c98ad2bda6ea5ac5b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7964, "upload_time": "2017-05-09T05:19:12", "url": "https://files.pythonhosted.org/packages/80/27/abe6d993cbb0f96dd2b51ff97939389d5d69b8b5c5180a7c434a83bbfb04/sower-1.0.3-py3-none-any.whl" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "fb96b9b9962b2feef1277a8e96c12bb1", "sha256": "cf665bcccf73db47c0989862225a1fdd1b7d453f3230c21e20bfff7707d5c5e7" }, "downloads": -1, "filename": "sower-1.0.4-py2-none-any.whl", "has_sig": false, "md5_digest": "fb96b9b9962b2feef1277a8e96c12bb1", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 8063, "upload_time": "2017-05-09T13:23:39", "url": "https://files.pythonhosted.org/packages/77/80/b63c8456cc6e2c20c093c63d27bb2d75b85313a3a6dd9d7fb5b8f8c15837/sower-1.0.4-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0f33e07675f9e8072e8fc3efa8d5e163", "sha256": "bc19777fcb2d1ca4b8c1fecf27def1d4b6062d1628b4754d22d68a6e58aa0568" }, "downloads": -1, "filename": "sower-1.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "0f33e07675f9e8072e8fc3efa8d5e163", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8059, "upload_time": "2017-05-09T13:22:55", "url": "https://files.pythonhosted.org/packages/e9/17/e494554962a2b9ae11a875cfcf5c279bdee7311befa21a1d2e2e684dc5bd/sower-1.0.4-py3-none-any.whl" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "14c40c3974a0e70c252929eb98f4979a", "sha256": "7f6231993430cbea10e8511f07bcc3a02b92ac69ba274e8e7847f15864e39c47" }, "downloads": -1, "filename": "sower-1.0.5-py2-none-any.whl", "has_sig": false, "md5_digest": "14c40c3974a0e70c252929eb98f4979a", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 8259, "upload_time": "2017-05-09T19:06:52", "url": "https://files.pythonhosted.org/packages/fc/ca/ea7033de3ccf69b062adda9798696358d2889f27a1154da4129afad2f151/sower-1.0.5-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "596175a55ce09a2bb15ee9e89873fa5f", "sha256": "7c229cac7a50c4fb4f8a847ab2d66631938e2a89beade2d1b4a3770cb388a717" }, "downloads": -1, "filename": "sower-1.0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "596175a55ce09a2bb15ee9e89873fa5f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8263, "upload_time": "2017-05-09T19:11:52", "url": "https://files.pythonhosted.org/packages/29/42/f44267c0c8c598b4c67d17a4eb2ebd0a8a66447f42aedb682697370874f8/sower-1.0.5-py3-none-any.whl" } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "251964cafa8513077d3c17deef6cacaf", "sha256": "6e6f0f0753716e1e35e1ed51c878a8efd96f7bf76ec2b8f792038e6a68504a92" }, "downloads": -1, "filename": "sower-1.0.6-py2-none-any.whl", "has_sig": false, "md5_digest": "251964cafa8513077d3c17deef6cacaf", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 8220, "upload_time": "2017-05-10T13:03:59", "url": "https://files.pythonhosted.org/packages/c6/62/0e65c590501aeeae5d7b50bfab8013bf5fe52a2403a64859f41314553d89/sower-1.0.6-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a571ca1367a08cbe8e7992c93d7b75ab", "sha256": "b951c7e0228ad0e2879eb7fe9eab69a729a8e7e37c5aeaf5a480da30cd3197d6" }, "downloads": -1, "filename": "sower-1.0.6-py3-none-any.whl", "has_sig": false, "md5_digest": "a571ca1367a08cbe8e7992c93d7b75ab", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8213, "upload_time": "2017-05-10T13:03:59", "url": "https://files.pythonhosted.org/packages/e7/9a/7a890f4d3fa6c916365e9c0ec654b094c05a634d596bb511ff0bfb7a2694/sower-1.0.6-py3-none-any.whl" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "2db34a2ba02b9de63509ad2f651d15c8", "sha256": "46e390207507cfeda82cf9758d4d9ba7b117a951b79f77a7f5aef6e1f588fe8c" }, "downloads": -1, "filename": "sower-1.1.0-py2-none-any.whl", "has_sig": false, "md5_digest": "2db34a2ba02b9de63509ad2f651d15c8", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 9521, "upload_time": "2017-05-11T13:42:11", "url": "https://files.pythonhosted.org/packages/db/04/9d51ad051813b964c4a18930ffc4d1ea10574acff3ba6be875d90f494cad/sower-1.1.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "df41a6a3ac02617fd3c93ba2560cabba", "sha256": "ffd990c0637b834a67eb5aeecaf430532305bb318ead8f5d0e8223fb56746020" }, "downloads": -1, "filename": "sower-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "df41a6a3ac02617fd3c93ba2560cabba", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9517, "upload_time": "2017-05-11T13:42:23", "url": "https://files.pythonhosted.org/packages/2f/14/8fbf4f678ef9cffbf36921e1d265eac6913221c7d706918f97f9a5a50eb3/sower-1.1.0-py3-none-any.whl" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "dd035ee981c68ab74c12e825207f672a", "sha256": "eb637c342b04b0dd9256be6e8aef22bcdee9cdb704d9a3518a9a60ec4ec2033c" }, "downloads": -1, "filename": "sower-1.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "dd035ee981c68ab74c12e825207f672a", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10630, "upload_time": "2017-05-12T01:14:18", "url": "https://files.pythonhosted.org/packages/42/f9/ac71a9b56ba9bedee8e262d579bf566ecbf7541e37bbaae7729efa2712e8/sower-1.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "feef4d02eb86fcf14f9890f38e08972a", "sha256": "2ea16fd396e62cbfb51782c0d2a9f31faeb2da8223b5282c6e352b1e8b68091c" }, "downloads": -1, "filename": "sower-1.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "feef4d02eb86fcf14f9890f38e08972a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10627, "upload_time": "2017-05-12T01:14:19", "url": "https://files.pythonhosted.org/packages/64/97/0c7ccf94b9daa2f17358820f1aa67c842509a3e90e17e4906a992b4da091/sower-1.1.1-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "dd035ee981c68ab74c12e825207f672a", "sha256": "eb637c342b04b0dd9256be6e8aef22bcdee9cdb704d9a3518a9a60ec4ec2033c" }, "downloads": -1, "filename": "sower-1.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "dd035ee981c68ab74c12e825207f672a", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10630, "upload_time": "2017-05-12T01:14:18", "url": "https://files.pythonhosted.org/packages/42/f9/ac71a9b56ba9bedee8e262d579bf566ecbf7541e37bbaae7729efa2712e8/sower-1.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "feef4d02eb86fcf14f9890f38e08972a", "sha256": "2ea16fd396e62cbfb51782c0d2a9f31faeb2da8223b5282c6e352b1e8b68091c" }, "downloads": -1, "filename": "sower-1.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "feef4d02eb86fcf14f9890f38e08972a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10627, "upload_time": "2017-05-12T01:14:19", "url": "https://files.pythonhosted.org/packages/64/97/0c7ccf94b9daa2f17358820f1aa67c842509a3e90e17e4906a992b4da091/sower-1.1.1-py3-none-any.whl" } ] }