{ "info": { "author": "", "author_email": "", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "winnan\n======\n\n **winnan**\n\n 1. (verb) to struggle, suffer, contend\n\n https://en.wiktionary.org/wiki/winnan\n\n*Because everything about managing files on Windows is terrible.*\n\n\nInstallation\n------------\n\n.. code-block:: console\n\n $ python -m pip install --upgrade winnan\n\n\nUsage\n-----\n\nUse the ``winnan.open()`` function exactly like using |Python's built-in open() function|_. It aims\nto be a drop-in replacement.\n\n.. |Python's built-in open() function| replace:: Python's built-in ``open()`` function\n.. _Python's built-in open() function: https://docs.python.org/3/library/functions.html#open\n\n.. code-block:: python\n\n import winnan\n\n with winnan.open(\"myfile\") as fileobj:\n pass\n\nThe file descriptor underlying the returned ``file`` object has the following two properties\n**on both POSIX and Windows systems**:\n\n1. The file descriptor is non-inheritable.\n\n2. The file can be *scheduled for deletion* while the file descriptor is still open.\n\n Saying \"scheduled for deletion\" rather than \"deleted\" is to be pedantic about how the file is put\n into a \"delete pending\" state on Windows until the last file handle is closed. See\n `Mercurial's developer documentation`_ as a reference for the semantics of certain operations on\n the file while it is in a \"delete pending\" state.\n\n.. _Mercurial's developer documentation: https://www.mercurial-scm.org/wiki/UnlinkingFilesOnWindows\n\n\nMotivation\n----------\n\nUnsurprisingly, the complications around managing files involve dealing with other processes.\nDepending on what the Python application is doing, there may be a need to deal with not only\nprocesses spawned by the Python application but also other processes running on the machine.\n\n1. As documented by PEP-446_, opening a file concurrently with spawning a subprocess may lead to the\n file descriptor being inherited unintentionally.\n\n The process cannot access the file because it is being used by another process.\n\n is perhaps the most classic representation of this issue on Windows. In modern versions of\n Python, the ``O_NOINHERIT`` flag is set by default when opening file descriptors on Windows.\n Setting it on the opened file descriptor prevents it from being inherited by a child process. The\n equivalent ``O_CLOEXEC`` flag is also set by default in modern versions of Python when opening\n file descriptors on POSIX systems.\n\n It is worth mentioning that due to limitations with being able to set ``close_fds=True`` when\n redirecting ``stdin``, ``stdout``, or ``stderr`` in older versions of Python, setting the\n ``O_NOINHERIT`` flag isn't sufficient for preventing files descriptors from being leaked when\n spawning subprocesses concurrently. Consider guarding all calls to ``subprocess.Popen`` with a\n ``threading.Lock`` instance to avoid this as an additional issue in older versions of Python.\n\n2. On POSIX systems, it is possible to ``unlink()`` a file while it is still open in another thread\n or process. On Windows, in all versions of Python, non-``O_TEMPORARY`` files are opened with\n ``FILE_SHARE_READ | FILE_SHARE_WRITE`` as their sharing mode. Omitting ``FILE_SHARE_DELETE``\n prevents another thread or process from attempting to delete a file while it is still open.\n\nThe purpose of this library is to mask these behavioral differences across different platforms and\nin older versions of Python.\n\n.. _PEP-446: https://www.python.org/dev/peps/pep-0446/\n\n\nReferences\n----------\n\nThere have been multiple attempts to address the ``FILE_SHARE_DELETE`` issue within CPython itself\nbut they unfortunately never succeeded in being integrated.\n\n* bpo-12939_: ``tempfile.NamedTemporaryFile`` not particularly useful on Windows\n* bpo-14243_: Support for opening files with ``FILE_SHARE_DELETE`` on Windows\n* bpo-15244_: Add new ``io.FileIO`` using the native Windows API\n\n.. _bpo-12939: https://bugs.python.org/issue12939\n.. _bpo-14243: https://bugs.python.org/issue14243\n.. _bpo-15244: https://bugs.python.org/issue15244\n\nStarting in Python 3.7, ``close_fds=True`` is able to be set even when redirecting ``stdin``,\n``stdout``, or ``stderr``.\n\n* bpo-19575_: ``subprocess``: on Windows, unwanted file handles are inherited by child processes\n in a multi-threaded application\n* bpo-19764_: ``subprocess``: use ``PROC_THREAD_ATTRIBUTE_HANDLE_LIST`` with ``STARTUPINFOEX`` on\n Windows Vista\n* bpo-33369_: Removing ``Popen`` log files in threads is racy on Windows\n\n.. _bpo-19575: https://bugs.python.org/issue19575\n.. _bpo-19764: https://bugs.python.org/issue19764\n.. _bpo-33369: https://bugs.python.org/issue33369", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/visemet/winnan", "keywords": "", "license": "MIT License", "maintainer": "Max Hirschhorn", "maintainer_email": "max.hirschhorn@mongodb.com", "name": "winnan", "package_url": "https://pypi.org/project/winnan/", "platform": "unix", "project_url": "https://pypi.org/project/winnan/", "project_urls": { "Homepage": "https://github.com/visemet/winnan" }, "release_url": "https://pypi.org/project/winnan/0.1.0/", "requires_dist": null, "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "summary": "More consistent file handling across POSIX and Windows systems", "version": "0.1.0" }, "last_serial": 4646804, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "3d6c6146e793989bfb030e3bb64cd8c1", "sha256": "d89ae0feb03a62ecca4dfef295daf801668cea3eb5034e296a2f2bb827c0e822" }, "downloads": -1, "filename": "winnan-0.1.0.tar.gz", "has_sig": false, "md5_digest": "3d6c6146e793989bfb030e3bb64cd8c1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 50384, "upload_time": "2018-12-30T19:42:04", "url": "https://files.pythonhosted.org/packages/8d/7f/be635e9992297b636c7ccf3dd60ab60f95a4db499d8e0d77e182531a2c11/winnan-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3d6c6146e793989bfb030e3bb64cd8c1", "sha256": "d89ae0feb03a62ecca4dfef295daf801668cea3eb5034e296a2f2bb827c0e822" }, "downloads": -1, "filename": "winnan-0.1.0.tar.gz", "has_sig": false, "md5_digest": "3d6c6146e793989bfb030e3bb64cd8c1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 50384, "upload_time": "2018-12-30T19:42:04", "url": "https://files.pythonhosted.org/packages/8d/7f/be635e9992297b636c7ccf3dd60ab60f95a4db499d8e0d77e182531a2c11/winnan-0.1.0.tar.gz" } ] }