{ "info": { "author": "Vincent Barth", "author_email": "vdbarth@posteo.at", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3 :: Only" ], "description": "=======\nAnyPath\n=======\nAnyPath makes it trivial to fetch remote resources and work with them locally.\nIt provides a normalized interface over different resources so that handling them is always consistent.\n\n.. code-block:: python\n\n with AnyPath('sftp://jane@host:/home/jane') as path:\n path.joinpath('somefile.txt').open().read()\n\nHere AnyPath will copy the directory `/home/jane` from a remote host via ssh to a local temporary directory.\nIt is then possible to work with the files locally. After we are done the temporary files are deleted.\nTherefore AnyPath is useful if you want to fetch e.g. some config files or a small project directory from a remote location and work with it locally.\n\n- `Installation`_\n\n - `Dependencies`_\n\n- `Basic Usage`_\n\n - `Persistance`_\n - `Providers and options`_\n\n - `Http`_\n - `Sftp`_\n - `Git`_\n - `Mercurial`_\n - `Local`_\n\n - `Checking for dependencies`_\n - `Limitations`_\n\n- `Contributing`_\n\n - `Writing a new PathProvider`_\n\n - `Decorators`_\n - `The fetch method`_\n\n- `License`_\n\n\nInstallation\n============\nTo install simply do::\n\n pip install anypath\n\nDependencies\n------------\nBy default AnyPath does not install the dependencies for the different providers. You should install them as needed:\n\n +-----------+---------------------------------+\n | Provider | Dependencies |\n +===========+=================================+\n | git | local git installation |\n +-----------+---------------------------------+\n | mercurial | local mercurial installation |\n +-----------+---------------------------------+\n | http | `pip install requests` |\n +-----------+---------------------------------+\n | sftp | `pip install paramiko` |\n +-----------+---------------------------------+\n | local | None |\n +-----------+---------------------------------+\n\n\nBasic Usage\n===========\nAnyPath uses :code:`pathproviders` to handle different remote resources. The resources are then fetched to a new temporary directory where you can work with them.\nThe newly fetched ressources are wrapped in a :code:`pathlib.Path`.\n\n.. code-block:: python\n\n from anypath.anypath import AnyPath, path_provider\n from anypath.pathprovider.http import HttpPath\n\n path_provider.add(HttpPath)\n\n with AnyPath('http://example.org') as path:\n path.open().read()\n\nFirst you register all the providers that you want to use (note: remember to install the dependencies per provider).\nNow you can open any uri that has a scheme known to one of the registered providers.\n\n +-----------+-----------------------------------------+\n | Provider | Schemes |\n +===========+=========================================+\n | git | - `git+http://` |\n | | - `git+https://` |\n | | - `git://` |\n +-----------+-----------------------------------------+\n | mercurial | - `hg+http://` |\n | | - `hg+https://` |\n +-----------+-----------------------------------------+\n | http | - `http://` |\n | | - `https://` |\n +-----------+-----------------------------------------+\n | sftp | - `sftp://` |\n | | - `ssh://` |\n +-----------+-----------------------------------------+\n | local | - `file://` |\n | | - `/` |\n | | - `./` |\n +-----------+-----------------------------------------+\n\nYou can use AnyPath either as a contextmanager (:code:`with AnyPath ...`) or directly by calling :code:`fetch()`.\nBeware that you will have to call :code:`close()` manually when not using the contextmanager to cleanup the temporary files.\n\n.. code-block:: python\n\n path_provider.add(HttpPath)\n ap = AnyPath('http://example.org')\n path = ap.fetch() # type: Path\n path.open().read()\n ap.close()\n\nPersistance\n-----------\nThe example so far was useful if you are only interested in the content of a fetched resource. They are created in a temporary folder, where you can work with them, and are deleted afterwards.\nSometimes however you may want to persist the remote resource outside of a temporary location.\n\n.. code-block:: python\n\n path_provider.add(HttpPath)\n\n with AnyPath('http://example.org', persist_dir='/your/local/path') as path:\n path.open().read()\n\nInstead of copying the files manually you can specify a :code:`persist_dir` when creating the AnyPath. The temporary resources will then be copied to that location.\nAs a result you will get the :code:`persist_dir` wrapped as an :code:`pathlib.Path` instead of the temporary location and you can directly work with it.\n\nProviders and options\n---------------------\nWhile the defaults for fetching resources might be fine for many use cases there are many situations where you might want to pass some options to a provider.\nYou might for example want to do a POST with an HttpPath or pass credentials to a GitPath.\n\nOptions are always passed as keyword arguments. Following you will find all providers and their available options.\n\nHttp\n^^^^\nThe options are passed to a requests.Request object, they behave the same and are named accordingly.\n\n.. code-block:: python\n\n AnyPath('http://example.org', method='GET', data=None, headers=None, params=None)\n\n========= ============================================================\nOption Description\n========= ============================================================\nmethod Default: 'GET'\n\n Specifies the HTTP method to be used as a string.\n\n E.g. POST, DELETE, PUT\n\n\ndata Default: None\n\n The body to attach to the request.\n\n If a dictionary is provided, form-encoding will take place.\n\n\nheaders Default: None\n\n A dictionary of headers to send in the request.\n\n\nparams Default: None\n\n A dictionary of URL parameters to append to the URL.\n========= ============================================================\n\nSftp\n^^^^\nThe path for Sftp is expected to be in the format :code:`sftp://user@host:/path/on/host`, additional options can be set via arguments.\n\n.. code-block:: python\n\n AnyPath('sftp://user@localhost:/path/on/host', password=None, private_key=None, port=22)\n\n============ ============================================================\nOption Description\n============ ============================================================\npassword Default: None\n\n The password for the user.\n\n Also used if private_key is given,\n and the key requires a password\n\n\nprivate_key Default: None\n\n The path to the local private_key (as a string)\n if it is used to login\n\n\nport Default: 22\n\n The ssh port to be used.\n============ ============================================================\n\nGit\n^^^\nNone\n\nMercurial\n^^^^^^^^^\nNone\n\nLocal\n^^^^^\nNone\n\nChecking for dependencies\n-------------------------\nBy default dependencies are only checked right before the appropriate PathProvider is called, i.e., at the moment the remote resources should be fetched.\nIt is possible to check for dependencies as soon as all PathProviders are registered. There are two methods to do that, :code:`get_requirements()` and :code:`check_requirements()`.\n:code:`get_requirements()` only returns a dictionary of all dependencies (modules and executables) that would be needed, while :code:`check_requirements()` fully checks for all dependencies to be present and would raise an exception if they are not:\n\n.. code-block:: python\n\n >>> path_provider.add(HttpPath, SftpPath, GitPath)\n >>> path_provider.get_requirements()\n {'modules': ['requests', 'paramiko'], 'executables': ['git']}\n\nIf the requirements for HttpPath (the requests module) would not be met calling :code:`check_requirements()` would raise an exception:\n\n.. code-block:: python\n\n >>> path_provider.add(HttpPath)\n >>> path_provider.check_requirements()\n ...anypath.dependencies.NotInstalledError: Python module requests is not installed.\n\n\nLimitations\n-----------\nYou might not want to use AnyPath if you are working with a huge remote resource.\nEverything is fetched to your local machine, which might take some time and cost a lot of space if you try to work with a whole filesystemn of a remote host for example.\nIt is also not intended do do updates to the remote resource since there is no mechanism to write changes back to the remote.\n\nContributing\n============\nYou can contribute in any of the following areas, no matter if it is your first OSS contribution or your thousandths.\nContributions are welcome for example:\n\n- If you find any issue or bug when using AnyPath\n- If you want to add to the documentation or fix incorrect or missing documentation.\n- If you want to add features or work on the codebase in general\n\nJust file an issue in the tracker first describing what you would like to do and then create a pull-request.\n\nWriting a new PathProvider\n--------------------------\nCreating a new PathProvider requires writing a new class; using it requires registering it via :code:`path_provider.add()`\n\nThe basic structure of a PathProvider looks like this:\n\n.. code-block:: python\n\n @pattern('protocol://')\n @required_executables('some_executable')\n @dependencies('some_py_module')\n class MyPath(BasePath):\n def __init__(self, protocol, path, persist_dir, some_option='default'):\n super().__init__(protocol, path, persist_dir)\n ...\n\n @BasePath.wrapped\n def fetch(self):\n ...\n\nHere a PathProvider MyPath is created, it registers a protocol that it can handle, declares some requirements and has a fetch method which does the actual work.\nThe PathProvider must always inherit from :code:`anypath.BasePath`.\n\nDecorators\n^^^^^^^^^^\nThere are three class decorators available for a PathProvider:\n\n:code:`pattern('')`\n\nThis decorator is required. It lists all patterns a path can start with on which the PathProvider can act. In the example MyPath registers the pattern :code:`protocol://`,\nmeaning whenever a path start with :code:`protocol://` MyPath will be called.\n\nA PathProvider can register more than one pattern, each pattern is passed as a single argument to the pattern decorator.\nThe HttpPath for example registers :code:`http://` and :code:`https://` using :code:`@pattern('http://', 'https://')`.\n\n\n:code:`required_executables('')`\n\nThis decorator is optional. It lists all required executables which must be available on the system to perform the tasks of the PathProvider.\nIn the example MyPath specifies, that :code:`some_executable` must exists and be callable from within the program.\n\nAnyPath checks for the existence via checking :code:`shutil.which(executable) is None` where :code:`executable` is the exectuable specified in :code:`required_executables()`.\n\n\n:code:`dependencies('')`\n\nThis decorator is optional. It lists all required python modules which must be available to be imported to perform the tasks of the PathProvider.\nIn the example MyPath specifies, that :code:`some_py_module` must exists and be importable.\n\nAnyPath will import the module via :code:`importlib.import_module(module)` where :code:`module` is the module specified in :code:`dependencies()`.\n\nThe fetch method\n^^^^^^^^^^^^^^^^\nThe class must include a :code:`fetch` method which will be called to fetch the remote resources.\nThe fetch method must have the method decorator :code:`@BasePath.wrapped`. Its main purpose is to call pre and post actions to fetching the resources.\nThose actions are creating a temporary directory and persisting the temporary files if needed.\n\nLicense\n=======\nAnyPath is licensed under \"Mozilla Public License Version 2.0\". See LICENSE.txt for the full license.\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/vaubarth/anypath", "keywords": "", "license": "Mozilla Public License 2.0 (MPL 2.0)", "maintainer": "", "maintainer_email": "", "name": "anypath", "package_url": "https://pypi.org/project/anypath/", "platform": "", "project_url": "https://pypi.org/project/anypath/", "project_urls": { "Homepage": "https://github.com/vaubarth/anypath" }, "release_url": "https://pypi.org/project/anypath/1.0.0/", "requires_dist": null, "requires_python": "", "summary": "AnyPath makes it trivial to fetch remote resources and work with them locally.", "version": "1.0.0" }, "last_serial": 3580532, "releases": { "0.5.1": [ { "comment_text": "", "digests": { "md5": "a8fa5510f15f8cc1bf774cf8d5c6e921", "sha256": "fb3b76957f42c5ab739c57c1654a34f07f83971bb0b0a68e87d9ee8c071c0a2f" }, "downloads": -1, "filename": "anypath-0.5.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a8fa5510f15f8cc1bf774cf8d5c6e921", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10770, "upload_time": "2018-01-30T07:08:35", "url": "https://files.pythonhosted.org/packages/ae/f5/568d702b97f837d1f3978f6707e4d632e2566f46071574dac7d071813a97/anypath-0.5.1-py3-none-any.whl" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "49d8ceebf9de8c8666faac17e5d7af27", "sha256": "60d8ae27ff4ec65b13e60b26e7f1490d090b20e20cc8353cf84bf0c99d509b29" }, "downloads": -1, "filename": "anypath-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "49d8ceebf9de8c8666faac17e5d7af27", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11340, "upload_time": "2018-01-31T07:41:12", "url": "https://files.pythonhosted.org/packages/16/73/405b0685da68522e40aea5cf47bef27003a09d097d2d430e166ae56fa16e/anypath-0.6.0-py3-none-any.whl" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "edb13959a62b0c65afd6a6f588c9f3c7", "sha256": "f98d8fda204b4e0b0014db337950dbf8c6628bd983ec1715690d033f5fa4e9d4" }, "downloads": -1, "filename": "anypath-0.7.0-py3-none-any.whl", "has_sig": false, "md5_digest": "edb13959a62b0c65afd6a6f588c9f3c7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13055, "upload_time": "2018-02-01T12:34:24", "url": "https://files.pythonhosted.org/packages/bf/cc/888289571169eeddc47e9a6b4447256afde898ce162ef5abc476f4ab34bd/anypath-0.7.0-py3-none-any.whl" } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "f9ad8d96337b4196ba4e105c749b6ceb", "sha256": "f93df39da41ba976e68e96b1cb1ed39c72466220be5f0e0060f6082850bc4f5d" }, "downloads": -1, "filename": "anypath-0.7.5-py3.6.egg", "has_sig": false, "md5_digest": "f9ad8d96337b4196ba4e105c749b6ceb", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 18724, "upload_time": "2018-02-05T07:41:18", "url": "https://files.pythonhosted.org/packages/82/13/0d8346ca9cc52ba4fdfa291bfdf4e4b1c4f271bd7e546270db29f8f25dae/anypath-0.7.5-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "f99d22975de2a48347163aac2f04a3c6", "sha256": "e3731d72a463d988ad90dd3c2ad1a589c8713e2d1bccdf712f188cecb0fec02e" }, "downloads": -1, "filename": "anypath-0.7.5-py3-none-any.whl", "has_sig": false, "md5_digest": "f99d22975de2a48347163aac2f04a3c6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12749, "upload_time": "2018-02-05T07:41:17", "url": "https://files.pythonhosted.org/packages/db/31/90e1fb1dff600b6f5198dee8293937c95a5f05b58b0095b806fa47810979/anypath-0.7.5-py3-none-any.whl" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "e54659e005d75ea83a6a32b6cc4c6597", "sha256": "7bed7db9070001e213b26ea396c77499345a230f62fb2c6ac6df4841b78c97dd" }, "downloads": -1, "filename": "anypath-0.8.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e54659e005d75ea83a6a32b6cc4c6597", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12855, "upload_time": "2018-02-06T07:31:35", "url": "https://files.pythonhosted.org/packages/81/70/efc97afd8b0b8f45d79ead6f736b38149a05265af02d2541dab2b92ace64/anypath-0.8.0-py3-none-any.whl" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "96b30355d6838de89c5b05cc0d5ebdad", "sha256": "64112ccf477aa6e605b37c73b682cb4255ac329979227cee006bfcd4ca057d55" }, "downloads": -1, "filename": "anypath-0.9.0-py3-none-any.whl", "has_sig": false, "md5_digest": "96b30355d6838de89c5b05cc0d5ebdad", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14068, "upload_time": "2018-02-08T10:03:09", "url": "https://files.pythonhosted.org/packages/b5/66/22c83e6b9a3989fee08c7118b12a0c8a4fcfdab9f80d78ad06aee8086835/anypath-0.9.0-py3-none-any.whl" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "86a2436c5a146842db9bca1cbab4c0be", "sha256": "87df0f837af2cde43b64ce2d7ad1e9380ca8734ef95be5311b78ccbb7708928c" }, "downloads": -1, "filename": "anypath-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "86a2436c5a146842db9bca1cbab4c0be", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15751, "upload_time": "2018-02-14T05:41:58", "url": "https://files.pythonhosted.org/packages/66/c6/af7893d7ce3d1588341112391347286e4944c645c4a26954eb38db1d5217/anypath-1.0.0-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "86a2436c5a146842db9bca1cbab4c0be", "sha256": "87df0f837af2cde43b64ce2d7ad1e9380ca8734ef95be5311b78ccbb7708928c" }, "downloads": -1, "filename": "anypath-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "86a2436c5a146842db9bca1cbab4c0be", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15751, "upload_time": "2018-02-14T05:41:58", "url": "https://files.pythonhosted.org/packages/66/c6/af7893d7ce3d1588341112391347286e4944c645c4a26954eb38db1d5217/anypath-1.0.0-py3-none-any.whl" } ] }