{ "info": { "author": "metagriffin", "author_email": "mg.pypi@uberdev.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "===================\nFile System Overlay\n===================\n\nFile System Overlay (FSO) allows *side-effect free* unit testing of\nfile I/O operations. It does this by creating a caching overlay over\nthe local file system, allowing read-through access, but storing\nmodifications in memory. These in-memory changes can be inspected, to\nvalidate unit tests, and when the test completes, all changes to the\nfile system will be vaporized and blown out to sea (to quote\nDr. Stanley Goodspeed:\nhttp://www.youtube.com/watch?v=K-uEbYq9kNU&t=6m29s).\n\n\nProject\n=======\n\n* Homepage: https://github.com/metagriffin/fso\n* Bugs: https://github.com/metagriffin/fso/issues\n\n\nTL;DR\n=====\n\nInstall:\n\n.. code-block:: bash\n\n $ pip install fso\n\nUse:\n\n.. code-block:: python\n\n import unittest, fso\n\n class MyTest(unittest.TestCase):\n\n def setUp(self):\n self.fso = fso.push()\n\n def tearDown(self):\n fso.pop()\n\n def test_fs_changes(self):\n\n self.assertFalse(os.path.exists('/etc/foobar.conf'))\n\n with open('/etc/foobar.conf', 'wb') as fp:\n fp.write('some-data')\n\n self.assertTrue(os.path.exists('/etc/foobar.conf'))\n self.assertEqual(open('/etc/foobar.conf', 'rb').read(), 'some-data')\n\n # BUT, when testing ends, /etc/foobar.conf will not exist! *awesome*! :)\n\n # you can also check that the expected changes are there (noting\n # that all paths are absolutized, dereferenced, and normalized):\n self.assertEqual(self.fso.changes, [\n 'add:/etc/foobar.conf',\n ])\n\n\nOverview\n========\n\nTraditionally, testing I/O operations on the file system requires\nmodifying the implementation so that there is a pluggable layer of\nfile operations that gets replaced with mocks when performing tests\n(http://stackoverflow.com/questions/2655697/python-unittest-howto).\n\nThis is, IMHO, a terrible approach, since it means that the real code\nis not being executed, and may well hide some very real bugs.\n\nAs an alternative, the FSO package switches out the implementation of\nthe low-level file system calls, and caches changes in-memory, never\nactually modifying the file system.\n\nAlthough this is a very \"pure\" approach, there are some gotchas...\nSo, currently, only basic file operations are supported (such as\ncreating and deleting files and directories) -- if you are doing more\ncomplex things such as opening unix domain sockets and working with\nblock-special devices, FSO may not be up to the task. But, if you\ndon't mind, please help identify those holes by either reporting\nissues or providing patches... any contributions will be merged and\nvery much appreciated!\n\n\nSupported Operations\n====================\n\nCurrently, only the following I/O functions have replacements\nimplemented:\n\n* builtin.open\n* os.symlink\n* os.stat\n* os.lstat\n* os.unlink\n* os.remove\n* os.listdir\n* os.mkdir\n* os.makedirs\n* os.rmdir\n* os.path.exists\n* os.path.lexists\n* os.access\n* os.path.islink\n\nMost other I/O operations are built on top of these, so they\nimplicitly work with FSO. **However**, because they use whatever\ninstrumented functions are currently in the global scope, this means\nthat they are not compatible with *multiple* levels of FSO overlays.\nSince that is not the typical FSO use-case, this is deemed an\nacceptable trade-off.\n\nExamples of I/O operations that are supported, but only when using a\nsingle active FSO layer:\n\n* os.walk\n* os.path.isdir\n* os.path.isfile\n\n\nKnown Limitations\n=================\n\n* File permissions are currently NOT enforced (and might be overkill),\n and overlayed directories report mode 0700, and overlayed files\n and symlinks report mode 0600.\n\n* File open modes of 'U' and 'rU' are silently treated as 'r'.\n\n* The following `stat` attributes are not available/managed:\n * st_ino\n * st_dev\n * st_nlink\n * st_uid\n * st_gid\n * st_atime\n * st_mtime\n * st_ctime\n\n* Since changes are explicitly stored in-memory, changes that exceed\n the local machine's memory will cause problems.\n\n* The following categories of filesystem entries will not work:\n * sockets\n * block special device files\n * character special device files\n * FIFOs (named pipes)\n\n\nUsage\n=====\n\nFSO supports context managers! In most cases, this is actually\nrecommend. The reason is that some unit testing frameworks, such as\nnose, do not report errors very well if an FSO layer is still\nactive. Using the context manager will ensure that the FSO is\nuninstalled before they need to report the errors. Example:\n\n.. code-block:: python\n\n import unittest, fso\n\n class TestWithContextManager(unittest.TestCase):\n\n def test_with_cm(self):\n\n self.assertFalse(os.path.exists('no-such-file'))\n\n with fso.push() as overlay:\n\n self.assertFalse(os.path.exists('no-such-file'))\n\n with open('no-such-file', 'wb') as fp:\n fp.write('created')\n\n os.unlink('/etc/hosts')\n os.mkdir('/tmp/my-test-directory')\n\n self.assertTrue(os.path.exists('no-such-file'))\n self.assertEqual(overlay.changes, [\n 'del:/etc/hosts',\n 'add:/path/to/cwd/no-such-file',\n 'add:/tmp/my-test-directory',\n ])\n\n self.assertFalse(os.path.exists('no-such-file'))\n self.assertFalse(os.path.exists('/etc/my-test-directory'))\n self.assertTrue(os.path.exists('/etc/hosts'))", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/metagriffin/fso", "keywords": "unit testing file system open read write layering protection", "license": "GPLv3+", "maintainer": null, "maintainer_email": null, "name": "fso", "package_url": "https://pypi.org/project/fso/", "platform": "any", "project_url": "https://pypi.org/project/fso/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/metagriffin/fso" }, "release_url": "https://pypi.org/project/fso/0.3.1/", "requires_dist": null, "requires_python": null, "summary": "File System Overlay - filesystem layering for unit testing", "version": "0.3.1" }, "last_serial": 1682763, "releases": { "0.0.1": [], "0.1.0": [ { "comment_text": "", "digests": { "md5": "f6ed504061bfb537e448f6e7df534502", "sha256": "ed038f322a77d4ab84b41fbfe7d2d1012bcd32cb5ed1a676083bf26b55005d46" }, "downloads": -1, "filename": "fso-0.1.0.tar.gz", "has_sig": false, "md5_digest": "f6ed504061bfb537e448f6e7df534502", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6933, "upload_time": "2013-10-20T03:14:00", "url": "https://files.pythonhosted.org/packages/a6/e3/fcad180748f083087c0192c3fa3a1d755b9ba912548b76c2aa923dcc42c4/fso-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "8d06e39e948699128b55d25f1ede5661", "sha256": "6716162c9514f49808e1c2d6ce149734049787595f5edca143d64b0e0c9d7d26" }, "downloads": -1, "filename": "fso-0.1.1.tar.gz", "has_sig": false, "md5_digest": "8d06e39e948699128b55d25f1ede5661", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11438, "upload_time": "2013-11-03T03:17:17", "url": "https://files.pythonhosted.org/packages/51/90/4ebcb36738cee2fa622f707b74dcd2580c663f9a78f3dc1c20940b795746/fso-0.1.1.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "09bfb79c3edb539f30bdbeb6e5a22dc2", "sha256": "1e9e51a54e23bd63169b6eca6e71ea11fd0beed04c02ed4755642c00625e3c16" }, "downloads": -1, "filename": "fso-0.1.3.tar.gz", "has_sig": false, "md5_digest": "09bfb79c3edb539f30bdbeb6e5a22dc2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12517, "upload_time": "2013-11-03T15:06:55", "url": "https://files.pythonhosted.org/packages/2b/c5/6e94299a66756607c4d77082b524c10c2e90cbc3cec9848f27de9918fa51/fso-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "926f2c2fc5cd1676bffcae604155199f", "sha256": "113d6dcfaf22934e6359d83e51ed66c3b93452899f62b7c25cb0767cfa9d7f35" }, "downloads": -1, "filename": "fso-0.1.4.tar.gz", "has_sig": false, "md5_digest": "926f2c2fc5cd1676bffcae604155199f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12705, "upload_time": "2013-11-03T17:00:12", "url": "https://files.pythonhosted.org/packages/0c/f3/88b03e619edcd62883364769e0ed4669811ed3b7df3021353d350955e2a8/fso-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "495839984040a2a2d864af48306934aa", "sha256": "61459ab8448b9e73904ee1173cb7776835f96792cd9b3e724c9dbb2d19beca54" }, "downloads": -1, "filename": "fso-0.1.5.tar.gz", "has_sig": false, "md5_digest": "495839984040a2a2d864af48306934aa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12716, "upload_time": "2013-11-03T17:35:20", "url": "https://files.pythonhosted.org/packages/21/aa/67a461869ee377d163305d6efbf66789233c325b9097bd804b11648db35a/fso-0.1.5.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "142c2c71ffeb81a1e0876e18f6539f72", "sha256": "7708807952b21852dfdc446a4b0fef3356d066dc2b09fe9b1b90691eb03fc46e" }, "downloads": -1, "filename": "fso-0.2.tar.gz", "has_sig": false, "md5_digest": "142c2c71ffeb81a1e0876e18f6539f72", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28535, "upload_time": "2014-01-16T23:35:10", "url": "https://files.pythonhosted.org/packages/e0/79/9a4b2fe5857229dbcb48016ea196add2882be2d5a5ba4c07022971fa00ba/fso-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "f9006cdd7c57931403d6e98344206927", "sha256": "30cdb56627f9e46fc476506cc5a35eac5aaf5c0584610a12eb537be92010f13f" }, "downloads": -1, "filename": "fso-0.3.tar.gz", "has_sig": false, "md5_digest": "f9006cdd7c57931403d6e98344206927", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28587, "upload_time": "2014-01-17T00:36:02", "url": "https://files.pythonhosted.org/packages/07/2d/d861344feb7b01c71db38ca56eba4169dcdf7bcbcbc5668fe501360248d4/fso-0.3.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "9315c89b54cc037bbebd1ee99ca91edb", "sha256": "d0888f116674b8975331a17cb80a69a24c802e3578efcd93ab8e6de15d2ca153" }, "downloads": -1, "filename": "fso-0.3.1.tar.gz", "has_sig": false, "md5_digest": "9315c89b54cc037bbebd1ee99ca91edb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27313, "upload_time": "2015-08-18T17:29:16", "url": "https://files.pythonhosted.org/packages/08/4a/56ddb8b4225dfe56a0ebc278d31c93b974e29eaf7a1f22e8f11788e3ccf7/fso-0.3.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9315c89b54cc037bbebd1ee99ca91edb", "sha256": "d0888f116674b8975331a17cb80a69a24c802e3578efcd93ab8e6de15d2ca153" }, "downloads": -1, "filename": "fso-0.3.1.tar.gz", "has_sig": false, "md5_digest": "9315c89b54cc037bbebd1ee99ca91edb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27313, "upload_time": "2015-08-18T17:29:16", "url": "https://files.pythonhosted.org/packages/08/4a/56ddb8b4225dfe56a0ebc278d31c93b974e29eaf7a1f22e8f11788e3ccf7/fso-0.3.1.tar.gz" } ] }