{ "info": { "author": "Matthew Wardrop", "author_email": "mpwardrop@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "`interface_meta` provides a convenient way to expose an extensible API with\nenforced method signatures and consistent documentation.\n\n- **Documentation:** See below (full documentation will come at some point).\n- **Source:** https://github.com/matthewwardrop/interface_meta\n- **Bug reports:** https://github.com/matthewwardrop/interface_meta/issues\n\n## Overview\n\nThis library has been extracted (with some modifications) from\n[`omniduct`](https://github.com/airbnb/omniduct), a library also principally\nwritten by this author, where it was central to the extensible plugin\narchitecture. It places an emphasis on the functionality required to create a\nwell-documented extensible plugin system, whereby the act of subclassing is\nsufficient to register the plugin and ensure compliance to the parent API. As\nsuch, this library boasts the following features:\n\n- All subclasses of an interface must conform to the parent's API.\n- Hierarchical runtime property existence and method signature checking. Methods\n are permitted to add additional *optional* arguments, but otherwise must\n conform to the API of their parent class (which themselves may have extended\n the API of the interface).\n- Subclass definition time hooks (e.g. for registration of subclasses into a\n library of plugins, etc).\n- Optional requirement for methods in subclasses to explicity decorate methods\n with an `override` decorator when replacing methods on an interface, making\n it clearer as to when a class is introducing new methods versus replacing\n those that form the part of the interface API.\n- Generation of clear docstrings on implementations that stitches together the\n base interface documentation with any downstream extensions and quirks.\n- Support for extracting the quirks documentation for a method from other method\n docstrings, in the event that subclass implementations are done in an internal\n method.\n- Compatibility with ABCMeta from the standard library.\n\n## Example code\n\n```\nfrom abc import abstractmethod, abstractproperty\nfrom six import with_metaclass\nfrom interface_meta import InterfaceMeta, override, quirk_docs\n\nclass MyInterface(with_metaclass(InterfaceMeta, object)):\n \"\"\"\n An example interface.\n \"\"\"\n\n INTERFACE_EXPLICIT_OVERRIDES = True\n INTERFACE_RAISE_ON_VIOLATION = False\n INTERFACE_SKIPPED_NAMES = {'__init__'}\n\n def __init__(self):\n \"\"\"\n MyInterface constructor.\n \"\"\"\n pass\n\n @abstractproperty\n def name(self):\n \"\"\"\n The name of this interface.\n \"\"\"\n pass\n\n @quirk_docs(method='_do_stuff')\n def do_stuff(self, a, b, c=1):\n \"\"\"\n Do things with the parameters.\n \"\"\"\n return self._do_stuff(a, b, c)\n\n @abstractmethod\n def _do_stuff(self, a, b, c):\n pass\n\nclass MyImplementation(MyInterface):\n \"\"\"\n This implementation of the example interface works nicely.\n \"\"\"\n\n @quirk_docs(method='_init', mro=False)\n def __init__(self, a):\n \"\"\"\n MyImplementation constructor.\n \"\"\"\n self._init(a)\n\n def _init(self, a):\n \"\"\"\n In this instance, we do nothing with a.\n \"\"\"\n pass\n\n @property\n @override\n def name(self):\n return \"Peter\"\n\n @override\n def _do_stuff(self, a, b, c):\n \"\"\"\n In this implementation, we sum the parameters.\n \"\"\"\n return a + b + c\n```\n\nRunning `help(MyImplementation)` reveals how the documentation is generated:\n\n```\nclass MyImplementation(MyInterface)\n | This implementation of the example interface works nicely.\n |\n | Method resolution order:\n | MyImplementation\n | MyInterface\n | builtins.object\n |\n | Methods defined here:\n |\n | __init__(self, a)\n | MyImplementation constructor.\n |\n | In this instance, we do nothing with a.\n |\n | do_stuff(self, a, b, c=1)\n | Do things with the parameters.\n |\n | MyImplementation Quirks:\n | In this implementation, we sum the parameters.\n ...\n```\n\n## Related projects and prior art\n\nThis library is released into an already crowded space, and the author would\nlike to recognise some of the already wonderful work done by others. The primary\ndifference between this and other libraries is typically these other libraries\nfocus more on abstracting interface definitions and compliance, and less on the\ndocumentation and plugin registration work. While this work overlaps with these\nprojects, its approach is sufficiently different (in the author's opinion)\nto warrant a separate library.\n\n- [`pure_interface`](https://github.com/seequent/pure_interface)\n- [`python-interface`](https://github.com/ssanderson/interface)\n\n`python-interface` has an emphasis on ensuring that implementations of various\ninterfaces *strictly* adhere to the methods and properties associated with\nthe interface, and that helpful errors are raised when this is violated.\n\nBy\ncomparison this library focusses on functional comformance to parent classes,\nwhereby methods on subclasses are allowed to include additional parameters. It\nalso focusses on ensuring that documentation for such quirks in method signatures are correctly composed into the final documentation rendered for that method.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/matthewwardrop/interface_meta", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "interface-meta", "package_url": "https://pypi.org/project/interface-meta/", "platform": "", "project_url": "https://pypi.org/project/interface-meta/", "project_urls": { "Homepage": "https://github.com/matthewwardrop/interface_meta" }, "release_url": "https://pypi.org/project/interface-meta/1.1.1/", "requires_dist": [ "funcsigs", "six", "decorator" ], "requires_python": "", "summary": "InterfaceMeta", "version": "1.1.1" }, "last_serial": 5363794, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "38d169869b5442b46a85ad87999a9429", "sha256": "c68597ae7510c578305222478c58429f7c372d790387187834d8ad25c6dab7d8" }, "downloads": -1, "filename": "interface_meta-0.1.0.tar.gz", "has_sig": false, "md5_digest": "38d169869b5442b46a85ad87999a9429", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5157, "upload_time": "2019-01-17T00:39:19", "url": "https://files.pythonhosted.org/packages/4d/ca/d3578344cc1f9e1e2d93e5a991f748721238499d5f1c61ecff305faa9561/interface_meta-0.1.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "b6861d461f97f9391676f1fbcc8a9851", "sha256": "20f0534b079dfe907183d40ecee94629e57663ab93312e5f0b51e8d0f0007345" }, "downloads": -1, "filename": "interface_meta-1.0.0.tar.gz", "has_sig": false, "md5_digest": "b6861d461f97f9391676f1fbcc8a9851", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11823, "upload_time": "2019-01-22T05:30:17", "url": "https://files.pythonhosted.org/packages/26/f8/586399c2001a196944fb37e00562a293bb1e73f30a9b5bdf3593a39e8870/interface_meta-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "91561a4e4d8d43b88d82466aa1675387", "sha256": "fe9e9c441b2d0e70177a708245697e89b56b8c2cb61a8752241b53aa2aa2a781" }, "downloads": -1, "filename": "interface_meta-1.0.1.tar.gz", "has_sig": false, "md5_digest": "91561a4e4d8d43b88d82466aa1675387", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11968, "upload_time": "2019-02-12T19:30:44", "url": "https://files.pythonhosted.org/packages/5c/c7/19af52a842459a9ba31b67ab39e1046bf0bcc5718a283b639d56eae2df7d/interface_meta-1.0.1.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "fbb07923d3d244eb1e6514126804cb9c", "sha256": "b0191da4067ec941894ab6c1976dd02f5f41102db57ed676addd1bc3779eb4bf" }, "downloads": -1, "filename": "interface_meta-1.1.0.tar.gz", "has_sig": false, "md5_digest": "fbb07923d3d244eb1e6514126804cb9c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15565, "upload_time": "2019-02-20T00:56:24", "url": "https://files.pythonhosted.org/packages/b0/d8/77362d028eea9c1409891c34bb303331f82a51ecceab47f5c9e41c4585f1/interface_meta-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "b54253e95e37166b766086b4912b6ab1", "sha256": "104002c17b5a01e0c89ebe230af1e7f8d12239b1e840efd4be1d98b1a569d8de" }, "downloads": -1, "filename": "interface_meta-1.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b54253e95e37166b766086b4912b6ab1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13382, "upload_time": "2019-06-05T18:49:48", "url": "https://files.pythonhosted.org/packages/ed/af/6fd509aa0ef824627cac3091192baed5d4ff8fd8763b5ea5b3c4a3a76a66/interface_meta-1.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2890dc05ac7424478b44dec741cc9d95", "sha256": "d0f3b7bf66892618de0e2ea4acec969d67a6f5f7ec2aa00064af621cfbf15278" }, "downloads": -1, "filename": "interface_meta-1.1.1.tar.gz", "has_sig": false, "md5_digest": "2890dc05ac7424478b44dec741cc9d95", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12157, "upload_time": "2019-06-05T18:49:50", "url": "https://files.pythonhosted.org/packages/78/8a/2dbe0124240ac24267205e3b83afc4d2c86f289d9689446e97b9a7ae70ff/interface_meta-1.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b54253e95e37166b766086b4912b6ab1", "sha256": "104002c17b5a01e0c89ebe230af1e7f8d12239b1e840efd4be1d98b1a569d8de" }, "downloads": -1, "filename": "interface_meta-1.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b54253e95e37166b766086b4912b6ab1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13382, "upload_time": "2019-06-05T18:49:48", "url": "https://files.pythonhosted.org/packages/ed/af/6fd509aa0ef824627cac3091192baed5d4ff8fd8763b5ea5b3c4a3a76a66/interface_meta-1.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2890dc05ac7424478b44dec741cc9d95", "sha256": "d0f3b7bf66892618de0e2ea4acec969d67a6f5f7ec2aa00064af621cfbf15278" }, "downloads": -1, "filename": "interface_meta-1.1.1.tar.gz", "has_sig": false, "md5_digest": "2890dc05ac7424478b44dec741cc9d95", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12157, "upload_time": "2019-06-05T18:49:50", "url": "https://files.pythonhosted.org/packages/78/8a/2dbe0124240ac24267205e3b83afc4d2c86f289d9689446e97b9a7ae70ff/interface_meta-1.1.1.tar.gz" } ] }