{ "info": { "author": "Erwan Lemonnier", "author_email": "erwan@lemonnier.se", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# PyMacaron Core\n\nA python framework that takes the Swagger/OpenAPI representation of a json REST\napi and spawns a Flask server implementing it, as well as a client library to\ncall that api.\n\n'pymacaron-core' is an underlying layer for the\n[pymacaron](http://pymacaron.com) framework. If your intent is to code REST\napis based on Flask and Swagger, [pymacaron](http://pymacaron.com) offers a lot\nof extra goodies compared to 'pymacaron-core'.\n\n## Purpose: micro-services made easy\n\nA typical Python micro-service will expose a REST api where each api endpoint\nis implemented by a Python method. This method will in turn call other\nmicro-services and process their reply.\n\nPyMacaron Core aims at greatly simplifying the scaffholding needed to code and\nrun a micro-service in Python:\n\n 1. Write a set of Swagger specifications describing each api, and defining\n the data formats received and returned by each endpoint. Each\n specification should have extra markup binding api endpoints to method\n names used to call, respectively implement, the endpoint.\n\n 2. Implement Python methods for each of the micro-service's endpoints, as\n described in the service's swagger specification.\n\n 3. PyMacaron Core generates client libraries for all apis, allowing to call\n api endpoints as normal Python methods. Call results are automatically\n unmarshalled from json into Python objects. The methods implementing our\n micro-service's api can now easily call other apis.\n\n 4. Tell PyMacaron Core which api to serve: it then populates a Flask app with\n each api route bound to its corresponding Python method. Incoming json\n objects are transparently validated and unmarshalled into Python objects,\n passed to the method, and the method's result marshalled back into json.\n\n\nPyMacaron Core relies on bravado-core for marshaling/unmarshaling and format\nvalidation.\n\n## Disclaimer\n\nPyMacaron Core is actively used in production, but undergoes major refactorings\non a regular basis. Its API is subject to change. It has been tested on python\n2.7, 3.4 and 3.5.\n\nAsynchronous support based on grequests was dropped after version 0.0.92\n\n## Usage\n\nFirst, load the Swagger specifications of all the services your server will use:\n\n```\n from pymacaron_core.swagger import ApiPool\n\n ApiPool.add('public', yaml_path='public.yaml')\n ApiPool.add('login', yaml_path='login.yaml')\n ApiPool.add('user', yaml_path='user.yaml', timeout=20)\n```\n\n\n## Generating Server\n\nIn the Swagger spec describing the server side, each endpoint that you want to\nhave auto-generated into the Flask app should have the 'x-bind-server'\nattribute set to the path of a python method that will take as argument an\nobject modelled on the endpoint's argument, and return an object matching that\nof the endpoint's reponses (See bravado-core for details):\n\nLet's implement a login endpoint as an example:\n\n```\n /login:\n post:\n summary: Login a user.\n produces:\n - application/json\n x-bind-server: myserver.handlers.do_login\n parameters:\n - in: body\n name: body\n description: User login credentials.\n required: true\n schema:\n $ref: \"#/definitions/Credentials\"\n responses:\n 200:\n description: API version\n schema:\n $ref: '#/definitions/Welcome'\n default:\n description: Error\n schema:\n $ref: '#/definitions/Error'\n```\n\nPopulate a Flask app with server endpoints for the 'login' api:\n\n```\n from flask import Flask\n from pymacaron_core.swagger import ApiPool\n\n app = Flask(__name__)\n ApiPool.add('login', yaml_path='login.yaml')\n ApiPool.login.spawn_api(app)\n```\n\nTo implement the 'do_login' endpoint, the file 'myserver/handlers' should\ncontain:\n\n```\n from flask import jsonify\n from pymacaron_core.swagger.apipool import ApiPool\n from pymacaron_core.exceptions import PyMacaronCoreException\n\n def do_login(credentials):\n if authenticate_user(credentials):\n # Get the class representing bravado-core Welcome objects\n Welcome = ApiPool.login.model.Welcome\n # Instantiate Welcome and return it\n return Welcome(message=\"Welcome!\")\n else:\n # Rise an error in the API's error format, directly as\n # a Flask response object\n r = jsonify({'error': 'INVALID_CREDENTIALS'})\n r.status_code = 401\n return r\n```\n\n## Decorating server methods:\n\nYou can tell PyMacaron Core to apply a decorator to all server methods, which\ncomes in handy for gathering analytics or crash data. To do that in the example\nabove, modify the server code to be like:\n\n```\n from flask import Flask\n from pymacaron_core.swagger import ApiPool\n\n app = Flask(__name__)\n ApiPool.add('login', yaml_path='login.yaml')\n\n # Optionaly: wrap all server endpoints with a decorator\n def analytics_wrapper(f):\n ...\n\n ApiPool.login.spawn_api(app, decorator=analytics_wrapper)\n```\n\n## Generating Client\n\nIn the Swagger spec describing the server you want to call, each endpoint that\nyou want to have auto-generated into the client library should have the\n'x-bind-client' attribute set to the path of a python method that will take as\nargument an object modelled on the endpoint's argument, and return an object\nmatching that of the endpoint's reponses (See bravado-core for details):\n\n```\n /version:\n get:\n summary: Return the API''s version.\n produces:\n - application/json\n x-bind-client: version\n responses:\n 200:\n description: API version\n schema:\n $ref: '#/definitions/Version'\n```\n\nCalling that server now looks like (assuming the server api is called 'public'):\n\n```\n from pymacaron_core.swagger import ApiPool\n\n # Call the /version endpoint on the host:port specified in the Swagger\n # spec, and return a Version object:\n version = ApiPool.public.client.version()\n```\n\nThe client method passes path and query parameters as kwarg arguments. The POST request body is passed\nas an instance of an ApiPool model. For example, to pass a request body:\n\n```\n # To call\n # 'POST v1/item' with the body {name: 'foo', surname: 'bar'}\n # where the endpoint was defined with:\n # /v1/user:\n # post:\n # parameters:\n # - in: body\n # name: body\n # schema:\n # $ref: \"#/definitions/NameSurname\"\n # x-bind-client: create_user\n\n res = ApiPool.example.client.create_user(\n ApiPool.example.model.NameSurname(\n name='foo',\n surname='bar'\n )\n )\n```\n\nFor example, to pass query and path arguments:\n\n```\n # Assuming the endpoint:\n # /v1/user/:\n # get:\n # parameters:\n # - in: path\n # name: id\n # type: string\n # - in: query\n # name: uppercase\n # type: boolean\n # x-bind-client: get_user\n\n user = ApiPool.example.client.get_user(\n id='user_9327234',\n uppercase=True\n )\n```\n\nAll client methods support the following extra kwarg parameters:\n\n* max_attempts: how many times the client should try calling the server\n endpoint upon failure. Defaults to 3, with an increasing delay of .5 seconds,\n 1.5, then 2.5, etc.\n\n* read_timeout: the read timeout in seconds, passed to the requests module.\n\n* connect_timeout: the connect timeout in seconds, passed to the requests module.\n\n* request_headers: a dictionary of extra headers to add to the HTTP request\n (The request already contains 'Content-Type'='application/json' by default).\n\nAs in:\n\n```\n results = ApiPool.search.client.search(\n query=query_words,\n page=0,\n country=country,\n request_headers={\n 'Authorization': 'Bearer %s' % token,\n },\n max_attempts=2\n )\n```\n\n## Authentication\n\nTODO: describe the 'x-decorate-request' and 'x-decorate-server' attributes of\nthe swagger spec + give example of using them to add-on authentication support.\n\n\n## Handling Errors\n\nPyMacaron Core may raise exceptions, for example if the server stub gets an\ninvalid request according to the swagger specification.\n\nHowever PyMacaron Core does not know how to format internal errors into an\nobject model fitting that of the loaded swagger specification. Instead, you\nshould provide the apipool with a callback to format exceptions into whatever\nobject you wish your api to return. Something like:\n\n```\n from pymacaron_core.swagger import ApiPool\n\n def my_error_formatter(e):\n \"\"\"Take an exception and return a proper swagger Error object\"\"\"\n return ApiPool.public.model.Error(\n type=type(e).__name__,\n raw=str(e),\n )\n\n ApiPool.add('public', yaml_path='public.yaml', error_callback=my_error_formatter)\n```\n\nInternal errors raised by PyMacaron Core are instances of pymacaron_core.exceptions.PyMacaronCoreException\n\n\n## Model persistence\n\nYou can plug-in object persistence into chosen models by way of the swagger\nfile.\n\nSpecify the 'x-persist' attributes in the swagger definition of models to make\npersistent, with as a value the package path to a custom class, like this:\n\n```\n definitions:\n Foo:\n type: object\n description: a foo\n x-persist: pym.test.PersistentFoo\n properties:\n foo:\n type: string\n format: foo\n description: bar\n```\n\nThe persistence class must implement the static methods 'load_from_db' and\n'save_to_db', like in:\n\n```\n class PersistentFoo():\n\n @staticmethod\n def load_from_db(*args, **kwargs):\n # Load object(s) from storage. Return a tupple\n pass\n\n @staticmethod\n def save_to_db(object, *args, **kwargs):\n # Put object into storage\n pass\n```\n\nPyMacaron Core will inject the methods 'save_to_db' and 'load_from_db' into the\ncorresponding model class and instances, so you can write:\n\n```\n # Retrieve instance Foo with id 12345 from storage\n f = api.model.Foo.load_from_db(id='12345')\n\n # Put this instance of Foo into storage\n f.save_to_db()\n```\n\nThe details of how to store the objects, as well as which arguments to pass the\nmethods and what they return, is all up to you.\n\n\n## Call ID and Call Path\n\nIf you have multiple micro-services passing objects among them, it is\nconvenient to mark all responses initiated by a given call to your public\nfacing API by a common unique call ID.\n\nPyMacaron does this automagically for you, by way of generating and passing\naround a custom HTTP header named 'PymCallerID'.\n\nIn the same spirit, every subsequent call initiated by a call to the public\nfacing API registers a path via the 'PymCallerPath' header, hence telling each\nserver the list of servers that have been called between the public facing API\nand the current server.\n\nThose are highly usefull when mapping the tree of internal API calls initiated\nby a given public API call, for analytic purposes.\n\nTo access the call ID and call path:\n\n```\n try:\n from flask import _app_ctx_stack as stack\n except ImportError:\n from flask import _request_ctx_stack as stack\n\n if hasattr(stack.top, 'call_id'):\n call_id = stack.top.call_id\n # call_id is a uuid.uuid4 string\n\n if hasattr(stack.top, 'call_path'):\n call_path = stack.top.call_pat\n # call_path is a '.'-separated list of api names\n # For example 'public.user.login' indicates we are in server 'login',\n # by way of servers 'user' then 'public'.\n```\n\n## Install\n-------\n\n```\n pip install pymacaron-core\n```\n\n## Author\n\nErwan Lemonnier
\n[github.com/pymacaron](https://github.com/pymacaron)
\n[github.com/erwan-lemonnier](https://github.com/erwan-lemonnier)
\n[www.linkedin.com/in/erwan-lemonnier/](https://www.linkedin.com/in/erwan-lemonnier/)", "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/pymacaron/pymacaron-core", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "pymacaron-core", "package_url": "https://pypi.org/project/pymacaron-core/", "platform": "any", "project_url": "https://pypi.org/project/pymacaron-core/", "project_urls": { "Homepage": "https://github.com/pymacaron/pymacaron-core" }, "release_url": "https://pypi.org/project/pymacaron-core/1.0.174/", "requires_dist": null, "requires_python": "", "summary": "Swagger + Flask + Bravado-core = auto-spawning of API server, client and data objects for Pymacaron", "version": "1.0.174", "yanked": false, "yanked_reason": null }, "last_serial": 9498315, "releases": { "1.0.127": [ { "comment_text": "", "digests": { "md5": "932839fb928d28a395bfa8b4abbce223", "sha256": "ad3540dc7400cd7d1db5e0bc4598ee2e2cbf9504b07f5eb0c98b47224bc8ca6b" }, "downloads": -1, "filename": "pymacaron-core-1.0.127.tar.gz", "has_sig": false, "md5_digest": "932839fb928d28a395bfa8b4abbce223", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23478, "upload_time": "2018-06-26T11:24:52", "upload_time_iso_8601": "2018-06-26T11:24:52.330801Z", "url": "https://files.pythonhosted.org/packages/67/35/fefcb2489b9cf61f4bb96dc4a1aa27275f5dc012fb7c07dbf661521ec2b3/pymacaron-core-1.0.127.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.128": [ { "comment_text": "", "digests": { "md5": "97a7f91c16c076c6f52119a6b06e5e77", "sha256": "384fb4337ec3c560de2661d52d09617fafa67c15321466f6b6fe217aaca61242" }, "downloads": -1, "filename": "pymacaron-core-1.0.128.tar.gz", "has_sig": false, "md5_digest": "97a7f91c16c076c6f52119a6b06e5e77", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23524, "upload_time": "2018-06-26T11:53:06", "upload_time_iso_8601": "2018-06-26T11:53:06.812702Z", "url": "https://files.pythonhosted.org/packages/27/5d/d70e5c9d026900210b08f12882adfadce8ff8c733877663566498f6f0440/pymacaron-core-1.0.128.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.129": [ { "comment_text": "", "digests": { "md5": "e99e7112f6a075dc6429f7026849de52", "sha256": "ed71e317ad6db81ea0702bc103a31ddcb41718b07fd277f4e4aa616555bf4617" }, "downloads": -1, "filename": "pymacaron-core-1.0.129.tar.gz", "has_sig": false, "md5_digest": "e99e7112f6a075dc6429f7026849de52", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23554, "upload_time": "2018-11-22T17:55:36", "upload_time_iso_8601": "2018-11-22T17:55:36.261782Z", "url": "https://files.pythonhosted.org/packages/40/f4/ef2c1293a6b0a29a6534b578578b7287ced0a27371aeb318114378cbe39d/pymacaron-core-1.0.129.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.130": [ { "comment_text": "", "digests": { "md5": "c9ff3df5fc836c278dc07f1954fa168d", "sha256": "f3da68a4d9ffc57199729df9ec1beb8bb7c0989ab87a3bfe81b1a042384bab5b" }, "downloads": -1, "filename": "pymacaron-core-1.0.130.tar.gz", "has_sig": false, "md5_digest": "c9ff3df5fc836c278dc07f1954fa168d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23634, "upload_time": "2018-12-07T11:53:00", "upload_time_iso_8601": "2018-12-07T11:53:00.067687Z", "url": "https://files.pythonhosted.org/packages/f0/fc/aac3c5e2ad8161a5c48bb38e445af439e129c894b8cf614f111ceb021230/pymacaron-core-1.0.130.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.138": [ { "comment_text": "", "digests": { "md5": "90fc98fba61d6190827f3bab5b7849e8", "sha256": "ea51433f8607ac0deaf313dc7b694ff0f609cd02923b0e9060d7360077161823" }, "downloads": -1, "filename": "pymacaron-core-1.0.138.tar.gz", "has_sig": false, "md5_digest": "90fc98fba61d6190827f3bab5b7849e8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25980, "upload_time": "2019-09-24T15:38:36", "upload_time_iso_8601": "2019-09-24T15:38:36.706869Z", "url": "https://files.pythonhosted.org/packages/d7/f6/9ff46dfb352483a3a7f7341d9cf3ef9c3474f387ca87d060bfa72960d866/pymacaron-core-1.0.138.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.142": [ { "comment_text": "", "digests": { "md5": "92705d356e703768690dbd7ae456bd2f", "sha256": "b6a34ab44e00bafeccbef5b9263aa8ddb069e69c544458201ee104d05f7ee4d2" }, "downloads": -1, "filename": "pymacaron-core-1.0.142.tar.gz", "has_sig": false, "md5_digest": "92705d356e703768690dbd7ae456bd2f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26389, "upload_time": "2019-09-25T08:29:17", "upload_time_iso_8601": "2019-09-25T08:29:17.262957Z", "url": "https://files.pythonhosted.org/packages/cc/08/d6b693fb219968c2274466dfc8e29d06edf2ee85c06b26aed357bd287e8f/pymacaron-core-1.0.142.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.143": [ { "comment_text": "", "digests": { "md5": "4c05c17c04f4e7e21533e0927724ebfd", "sha256": "3f64b433bb5bd5ce80adc70fcdefb9798a3d6be9430e6ddc3362ff4b8106ea6b" }, "downloads": -1, "filename": "pymacaron-core-1.0.143.tar.gz", "has_sig": false, "md5_digest": "4c05c17c04f4e7e21533e0927724ebfd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26553, "upload_time": "2019-09-25T09:03:32", "upload_time_iso_8601": "2019-09-25T09:03:32.533269Z", "url": "https://files.pythonhosted.org/packages/a8/ba/ee4aea8d14e328cc2ffd2122384c13a7b4164baf41279f2cb44d548ac8a0/pymacaron-core-1.0.143.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.144": [ { "comment_text": "", "digests": { "md5": "0deaf71bb48d825b4e7fc1d404f0858c", "sha256": "3f249d2f0f2477ed18fcd95d99d3b1f62a3a040ac6f71e9809753f54a13cf9c0" }, "downloads": -1, "filename": "pymacaron-core-1.0.144.tar.gz", "has_sig": false, "md5_digest": "0deaf71bb48d825b4e7fc1d404f0858c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26363, "upload_time": "2019-10-11T07:33:39", "upload_time_iso_8601": "2019-10-11T07:33:39.675865Z", "url": "https://files.pythonhosted.org/packages/16/26/4f62f8422e581671d19b1f76becf6466b1fe4a67293fd5b0f07bbf39e043/pymacaron-core-1.0.144.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.146": [ { "comment_text": "", "digests": { "md5": "d8a86579942ff6b08502931878e6a8ce", "sha256": "277cc5c72254f2767e435e3455187432bba2b43ecc5b91081359868a202f0847" }, "downloads": -1, "filename": "pymacaron-core-1.0.146.tar.gz", "has_sig": false, "md5_digest": "d8a86579942ff6b08502931878e6a8ce", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26388, "upload_time": "2019-10-16T16:44:51", "upload_time_iso_8601": "2019-10-16T16:44:51.470780Z", "url": "https://files.pythonhosted.org/packages/3c/8a/864f586012d4fb407114057cce71c8693fa3903139516b91eb747c3d8779/pymacaron-core-1.0.146.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.148": [ { "comment_text": "", "digests": { "md5": "c0b78679664ed1bbb39b7cfa1b6c8ce7", "sha256": "f5da2fa3fb8a7b3959826dda96d4c61ff67a04eb0f7527ce5a70963f35a79ded" }, "downloads": -1, "filename": "pymacaron-core-1.0.148.tar.gz", "has_sig": false, "md5_digest": "c0b78679664ed1bbb39b7cfa1b6c8ce7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26434, "upload_time": "2019-10-19T05:24:29", "upload_time_iso_8601": "2019-10-19T05:24:29.013008Z", "url": "https://files.pythonhosted.org/packages/48/74/9579892f0c70a01e48e72866a8d6eba0af08c583474754a15dcec340d939/pymacaron-core-1.0.148.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.149": [ { "comment_text": "", "digests": { "md5": "62ac6aaad408581251f08e43552af051", "sha256": "fadce9bef08998b773c162718fbee88aba15a0c7bb7c87d443a12308da40495a" }, "downloads": -1, "filename": "pymacaron-core-1.0.149.tar.gz", "has_sig": false, "md5_digest": "62ac6aaad408581251f08e43552af051", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26436, "upload_time": "2019-10-19T05:25:49", "upload_time_iso_8601": "2019-10-19T05:25:49.419292Z", "url": "https://files.pythonhosted.org/packages/13/de/542f4588f16932e2ced50a1bd8f473fc1204ac79041da0f578a21069ef07/pymacaron-core-1.0.149.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.150": [ { "comment_text": "", "digests": { "md5": "2438996b516fb93a366223b704c199a2", "sha256": "ad411cb36dfa7cdc0e0be92d43a2207384662837bb0879b98ca02ac28852f1f2" }, "downloads": -1, "filename": "pymacaron-core-1.0.150.tar.gz", "has_sig": false, "md5_digest": "2438996b516fb93a366223b704c199a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26437, "upload_time": "2019-10-19T10:15:00", "upload_time_iso_8601": "2019-10-19T10:15:00.006780Z", "url": "https://files.pythonhosted.org/packages/85/c3/ff93d903c671d015cf0127ed5f8e2ab77458b83433455e6a5ae156950336/pymacaron-core-1.0.150.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.151": [ { "comment_text": "", "digests": { "md5": "79d172ee880179d5ee665802552f823e", "sha256": "2c58ceca98e22a72f2c779acaad8f7707a733646d9e580b875fd85e50a2f024a" }, "downloads": -1, "filename": "pymacaron-core-1.0.151.tar.gz", "has_sig": false, "md5_digest": "79d172ee880179d5ee665802552f823e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26386, "upload_time": "2019-10-19T16:34:54", "upload_time_iso_8601": "2019-10-19T16:34:54.243275Z", "url": "https://files.pythonhosted.org/packages/05/be/7ec1003f47831c272b20f37f5f80e159fc8da87e58fe1faa38a7a6af3140/pymacaron-core-1.0.151.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.152": [ { "comment_text": "", "digests": { "md5": "8c038c7fa470e3eaa6ae7d394abec46d", "sha256": "2513a8e0088f4876c300a7a0c7b4978d8ae8f0b0dcedb879dec7b42857cc5a62" }, "downloads": -1, "filename": "pymacaron-core-1.0.152.tar.gz", "has_sig": false, "md5_digest": "8c038c7fa470e3eaa6ae7d394abec46d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26478, "upload_time": "2019-10-19T19:23:26", "upload_time_iso_8601": "2019-10-19T19:23:26.827449Z", "url": "https://files.pythonhosted.org/packages/60/40/1276c2dfc0ab307ae65fa052e403c679acc5646dd20a18c37fbc9d7f2990/pymacaron-core-1.0.152.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.154": [ { "comment_text": "", "digests": { "md5": "6e9821b0db93ef569caafe1b8d7d0e5e", "sha256": "cc272e57cd1c5d00b1ddff144d52211364e76cbcfc5e5c02c584162da48b9628" }, "downloads": -1, "filename": "pymacaron-core-1.0.154.tar.gz", "has_sig": false, "md5_digest": "6e9821b0db93ef569caafe1b8d7d0e5e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26492, "upload_time": "2019-10-23T06:55:21", "upload_time_iso_8601": "2019-10-23T06:55:21.014799Z", "url": "https://files.pythonhosted.org/packages/cc/31/a14870bae54f94fb79b8ec14f02c41ab6dc9dd1e226a2b2c9dd802fb3887/pymacaron-core-1.0.154.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.156": [ { "comment_text": "", "digests": { "md5": "6c1b5a36d179c373bf16dc8b8bd73e32", "sha256": "4b7ea2d34fe19d2c28d3ad40c046e6104fe90df5f5fa816711f3cda8d899cdac" }, "downloads": -1, "filename": "pymacaron-core-1.0.156.tar.gz", "has_sig": false, "md5_digest": "6c1b5a36d179c373bf16dc8b8bd73e32", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26637, "upload_time": "2019-11-08T13:17:21", "upload_time_iso_8601": "2019-11-08T13:17:21.443574Z", "url": "https://files.pythonhosted.org/packages/ed/39/d7efb229923fe08546248f8b2bcc828a6a24168a5461c4e4a2a738245365/pymacaron-core-1.0.156.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.157": [ { "comment_text": "", "digests": { "md5": "081d27f7c82268e5d5ac43d151241537", "sha256": "a073c7ca38bccbda4da8b40f01169c6ab149a2d9666d0129b794c076c09df70a" }, "downloads": -1, "filename": "pymacaron-core-1.0.157.tar.gz", "has_sig": false, "md5_digest": "081d27f7c82268e5d5ac43d151241537", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26650, "upload_time": "2019-11-08T20:48:49", "upload_time_iso_8601": "2019-11-08T20:48:49.864364Z", "url": "https://files.pythonhosted.org/packages/d1/1c/54b28cb0fcf52e5cf4d57c12769beaac3a83bf1e7b9f60a1eeaafdc78f64/pymacaron-core-1.0.157.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.158": [ { "comment_text": "", "digests": { "md5": "820767ee6f85aa0fb0fbd10899f569d4", "sha256": "630f2bd1e9f8656c692a699e095dc970d343383523f51fef869b177ca900a040" }, "downloads": -1, "filename": "pymacaron-core-1.0.158.tar.gz", "has_sig": false, "md5_digest": "820767ee6f85aa0fb0fbd10899f569d4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27075, "upload_time": "2019-11-15T11:22:11", "upload_time_iso_8601": "2019-11-15T11:22:11.695799Z", "url": "https://files.pythonhosted.org/packages/3d/1d/a1f4f02bd3bafcfcebf9eb3f22cb977e11464546ee5bca901ed7a2c7fbe0/pymacaron-core-1.0.158.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.159": [ { "comment_text": "", "digests": { "md5": "b5eeadb50c902f3e353e1b97946fc57b", "sha256": "36f1fbb22f7bd36aaff6a27362553fbae6fa89db5ac81b358a414df663d7a63d" }, "downloads": -1, "filename": "pymacaron-core-1.0.159.tar.gz", "has_sig": false, "md5_digest": "b5eeadb50c902f3e353e1b97946fc57b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27051, "upload_time": "2019-11-15T11:23:03", "upload_time_iso_8601": "2019-11-15T11:23:03.134203Z", "url": "https://files.pythonhosted.org/packages/ae/15/522848a2af7fe123851ec5c446ff4c124c1ada0cd551f9a1b7877ab2d187/pymacaron-core-1.0.159.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.160": [ { "comment_text": "", "digests": { "md5": "0437dc9db3c32e558ea2fea71b371396", "sha256": "31571216e3e20a2ebc1a997505bf051962325c2e22cfd4a5400a5ed9f8c411d1" }, "downloads": -1, "filename": "pymacaron-core-1.0.160.tar.gz", "has_sig": false, "md5_digest": "0437dc9db3c32e558ea2fea71b371396", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27072, "upload_time": "2019-11-15T12:30:00", "upload_time_iso_8601": "2019-11-15T12:30:00.693641Z", "url": "https://files.pythonhosted.org/packages/7a/80/f4f04489cc2a78e7a70dee9788150d5be5ba34721fd35203c1a632498dd5/pymacaron-core-1.0.160.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.161": [ { "comment_text": "", "digests": { "md5": "1435936acb40af9304f5ef1bb1c9fb35", "sha256": "27f44c1a68c1852064bedb4e037a896f560ce1a323c5a6ca8a8707f57763c8a1" }, "downloads": -1, "filename": "pymacaron-core-1.0.161.tar.gz", "has_sig": false, "md5_digest": "1435936acb40af9304f5ef1bb1c9fb35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32393, "upload_time": "2019-12-01T08:35:59", "upload_time_iso_8601": "2019-12-01T08:35:59.938064Z", "url": "https://files.pythonhosted.org/packages/4f/17/c8225b4f9a5ef045997e7c8a875a807f24f15e631eefe99dbd4a8f192ca9/pymacaron-core-1.0.161.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.162": [ { "comment_text": "", "digests": { "md5": "c8c1dc76ce6e9b1b86f8dd5a5e92e724", "sha256": "82d6600721fb7249dab71a439ae50e60a2d325d21e055b508baf862ab0ee9d08" }, "downloads": -1, "filename": "pymacaron-core-1.0.162.tar.gz", "has_sig": false, "md5_digest": "c8c1dc76ce6e9b1b86f8dd5a5e92e724", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32393, "upload_time": "2019-12-01T08:37:31", "upload_time_iso_8601": "2019-12-01T08:37:31.301904Z", "url": "https://files.pythonhosted.org/packages/1f/be/c06247655735cc8209273da6a145d0f507b7162b6e0bf91c98df075c9041/pymacaron-core-1.0.162.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.163": [ { "comment_text": "", "digests": { "md5": "1ab2ed6103eefcfcf7b9c53c01cc597f", "sha256": "31a8376df035cf708961f53f361fbc787d243946dee9296a2aaae8762b17f4d8" }, "downloads": -1, "filename": "pymacaron-core-1.0.163.tar.gz", "has_sig": false, "md5_digest": "1ab2ed6103eefcfcf7b9c53c01cc597f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32420, "upload_time": "2019-12-02T13:34:43", "upload_time_iso_8601": "2019-12-02T13:34:43.105631Z", "url": "https://files.pythonhosted.org/packages/4a/f1/4ff48cc71489989e23fec08ec5231438d8652739ca188ae0499f547e8a71/pymacaron-core-1.0.163.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.164": [ { "comment_text": "", "digests": { "md5": "f1628a6a5c53ecb413f6a8eff1dc277a", "sha256": "00f30cf56ef4edf4c5ae849192210b1f8a3fbb3fea3fe7415c4bb898541f01a6" }, "downloads": -1, "filename": "pymacaron-core-1.0.164.tar.gz", "has_sig": false, "md5_digest": "f1628a6a5c53ecb413f6a8eff1dc277a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32415, "upload_time": "2019-12-02T13:36:07", "upload_time_iso_8601": "2019-12-02T13:36:07.870311Z", "url": "https://files.pythonhosted.org/packages/f9/5b/50b430aa5924b9b24c9eacd914e92f46f5b4e0dba7439b137a2ff939f5a5/pymacaron-core-1.0.164.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.165": [ { "comment_text": "", "digests": { "md5": "8bd688c7a4486e46d94f2ea2cd220e42", "sha256": "a97bae768d6aa94f4245e333a11d9cacff6b143103fe9005c5985a8270a80455" }, "downloads": -1, "filename": "pymacaron-core-1.0.165.tar.gz", "has_sig": false, "md5_digest": "8bd688c7a4486e46d94f2ea2cd220e42", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32414, "upload_time": "2019-12-17T06:50:53", "upload_time_iso_8601": "2019-12-17T06:50:53.598374Z", "url": "https://files.pythonhosted.org/packages/f7/b2/f782c457b426828e675256c22af6d9bb2cebb2748d4657834c10aca28ae9/pymacaron-core-1.0.165.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.166": [ { "comment_text": "", "digests": { "md5": "f38461ad91e06298a23cb9ffa3bc9d2f", "sha256": "b5469a9c87004ea7b204c8edd78c388cbaea7db9f19610c61eff2a1d46ba965e" }, "downloads": -1, "filename": "pymacaron-core-1.0.166.tar.gz", "has_sig": false, "md5_digest": "f38461ad91e06298a23cb9ffa3bc9d2f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32630, "upload_time": "2020-03-28T14:13:51", "upload_time_iso_8601": "2020-03-28T14:13:51.941359Z", "url": "https://files.pythonhosted.org/packages/f6/39/5d23a8d4b05b4fb5712b6c4f272c44f073939f4da9fee4cdbe3b94823fed/pymacaron-core-1.0.166.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.167": [ { "comment_text": "", "digests": { "md5": "2c67279c4636bb86ff01b73fe7746ede", "sha256": "71e5c81fe603f826889c3525755349e03139096bdf34a6cd97f5902c999bc2c0" }, "downloads": -1, "filename": "pymacaron-core-1.0.167.tar.gz", "has_sig": false, "md5_digest": "2c67279c4636bb86ff01b73fe7746ede", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32629, "upload_time": "2020-03-31T16:44:55", "upload_time_iso_8601": "2020-03-31T16:44:55.182013Z", "url": "https://files.pythonhosted.org/packages/5e/72/5788a533b67c75f5ca348cf4e8f9bf9c1719a9205259bad0f1e257a4a7c6/pymacaron-core-1.0.167.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.168": [ { "comment_text": "", "digests": { "md5": "43773100c89f2c54c6ac499fce864a4b", "sha256": "954564d9a70e5afe7b3a72cca8e4e2d628d3a2c87ebba584d1e67d4e1e8764b3" }, "downloads": -1, "filename": "pymacaron-core-1.0.168.tar.gz", "has_sig": false, "md5_digest": "43773100c89f2c54c6ac499fce864a4b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32875, "upload_time": "2020-07-03T04:42:40", "upload_time_iso_8601": "2020-07-03T04:42:40.995061Z", "url": "https://files.pythonhosted.org/packages/ac/95/d28c32a3668e7a43c588d09cfe7ff839ab49466c9c21a9af831450d9ce68/pymacaron-core-1.0.168.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.169": [ { "comment_text": "", "digests": { "md5": "7bd8e2f3430bbd14247b53a64560f43e", "sha256": "a67c78b14b780c9abf686b914667a650956f5e2c880a097622c63b18639d017e" }, "downloads": -1, "filename": "pymacaron-core-1.0.169.tar.gz", "has_sig": false, "md5_digest": "7bd8e2f3430bbd14247b53a64560f43e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32833, "upload_time": "2020-07-03T13:34:06", "upload_time_iso_8601": "2020-07-03T13:34:06.129235Z", "url": "https://files.pythonhosted.org/packages/cd/2f/a11a5b22cf3ae737d3a5a26fd097132b972034f4fa63fb4340cfa9095612/pymacaron-core-1.0.169.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.170": [ { "comment_text": "", "digests": { "md5": "96888a2e3191e715e5c0866ab402abec", "sha256": "db39ef5d8791596a02c48446620ff311a67fbe3987c986df58594c1fc167271a" }, "downloads": -1, "filename": "pymacaron-core-1.0.170.tar.gz", "has_sig": false, "md5_digest": "96888a2e3191e715e5c0866ab402abec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32858, "upload_time": "2020-07-27T11:42:46", "upload_time_iso_8601": "2020-07-27T11:42:46.139551Z", "url": "https://files.pythonhosted.org/packages/4c/9e/39c6fe5de53a0d8f064fac31fc33d2fdc87c627779a34cfaeb70b566f710/pymacaron-core-1.0.170.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.171": [ { "comment_text": "", "digests": { "md5": "12b5c90cdb3ed1912fe2e048f0642e2e", "sha256": "5af2d797b1f4b41ce1a039b2b8d2a3589a2b07aa3033d8e81c3923fb4da1f3db" }, "downloads": -1, "filename": "pymacaron-core-1.0.171.tar.gz", "has_sig": false, "md5_digest": "12b5c90cdb3ed1912fe2e048f0642e2e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32989, "upload_time": "2021-01-14T13:51:39", "upload_time_iso_8601": "2021-01-14T13:51:39.240100Z", "url": "https://files.pythonhosted.org/packages/ed/bb/7f3205830752260341a3c9567e63ac0c14b8871ac9269241926ff16de01e/pymacaron-core-1.0.171.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.172": [ { "comment_text": "", "digests": { "md5": "f115d2aef66a9f546ba71bca8414dc2b", "sha256": "d605c7ff9fc0f9c3553e0b8e5d729fa2804e8bd859185e46dad41124b1851b74" }, "downloads": -1, "filename": "pymacaron-core-1.0.172.tar.gz", "has_sig": false, "md5_digest": "f115d2aef66a9f546ba71bca8414dc2b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33002, "upload_time": "2021-02-04T10:51:51", "upload_time_iso_8601": "2021-02-04T10:51:51.794521Z", "url": "https://files.pythonhosted.org/packages/04/72/7ba35c70cd002aa1897d1dce1b164cfb116ff2719a2a94ff3cbd5a779977/pymacaron-core-1.0.172.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.173": [ { "comment_text": "", "digests": { "md5": "366a9bc63c1911e4eeeb57518f1a67a2", "sha256": "a42fff634553c612dc8a0503b1605c7554204dec9c7ae91e66e26413e3bb5a4e" }, "downloads": -1, "filename": "pymacaron-core-1.0.173.tar.gz", "has_sig": false, "md5_digest": "366a9bc63c1911e4eeeb57518f1a67a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33042, "upload_time": "2021-02-23T10:09:02", "upload_time_iso_8601": "2021-02-23T10:09:02.065486Z", "url": "https://files.pythonhosted.org/packages/76/fb/7cd9bc4da20fc5b1b9b42f43fb2d95e7c218b13c78689257d8575098efe4/pymacaron-core-1.0.173.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.174": [ { "comment_text": "", "digests": { "md5": "ae88e08872224d3a2a89108cb150da5c", "sha256": "bf4d783ec55f911b0e70e62cdc412337eed142bbafba2e53c5ec39fbcb2ab862" }, "downloads": -1, "filename": "pymacaron-core-1.0.174.tar.gz", "has_sig": false, "md5_digest": "ae88e08872224d3a2a89108cb150da5c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33020, "upload_time": "2021-02-23T10:47:53", "upload_time_iso_8601": "2021-02-23T10:47:53.414241Z", "url": "https://files.pythonhosted.org/packages/0d/27/e2232ef8d362c3f44a8038db0d33ddfa8560f159252fcf1f1beebce1a332/pymacaron-core-1.0.174.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ae88e08872224d3a2a89108cb150da5c", "sha256": "bf4d783ec55f911b0e70e62cdc412337eed142bbafba2e53c5ec39fbcb2ab862" }, "downloads": -1, "filename": "pymacaron-core-1.0.174.tar.gz", "has_sig": false, "md5_digest": "ae88e08872224d3a2a89108cb150da5c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33020, "upload_time": "2021-02-23T10:47:53", "upload_time_iso_8601": "2021-02-23T10:47:53.414241Z", "url": "https://files.pythonhosted.org/packages/0d/27/e2232ef8d362c3f44a8038db0d33ddfa8560f159252fcf1f1beebce1a332/pymacaron-core-1.0.174.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }