{ "info": { "author": "Daniel Fernandes Martins", "author_email": "daniel.tritone@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries" ], "description": "\nPyBreaker\n=========\n\n.. image:: https://travis-ci.org/danielfm/pybreaker.svg?branch=master\n :target: https://travis-ci.org/danielfm/pybreaker\n\nPyBreaker is a Python implementation of the Circuit Breaker pattern, described\nin Michael T. Nygard's book `Release It!`_.\n\nIn Nygard's words, *\"circuit breakers exists to allow one subsystem to fail\nwithout destroying the entire system. This is done by wrapping dangerous\noperations (typically integration points) with a component that can circumvent\ncalls when the system is not healthy\"*.\n\n\nFeatures\n--------\n\n* Configurable list of excluded exceptions (e.g. business exceptions)\n* Configurable failure threshold and reset timeout\n* Support for several event listeners per circuit breaker\n* Can guard generator functions\n* Functions and properties for easy monitoring and management\n* Thread-safe\n* Optional redis backing\n* Optional support for asynchronous Tornado calls\n\n\nRequirements\n------------\n\n* `Python`_ 3.6+\n\n\nInstallation\n------------\n\nRun the following command line to download the latest stable version of\nPyBreaker from `PyPI`_::\n\n $ easy_install -U pybreaker\n\nIf you are a `Git`_ user, you might want to download the current development\nversion::\n\n $ git clone git://github.com/danielfm/pybreaker.git\n $ cd pybreaker\n $ python setup.py test\n $ python setup.py install\n\n\nUsage\n-----\n\nThe first step is to create an instance of ``CircuitBreaker`` for each\nintegration point you want to protect against::\n\n import pybreaker\n\n # Used in database integration points\n db_breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=60)\n\n\n``CircuitBreaker`` instances should live globally inside the application scope,\ne.g., live across requests.\n\n.. note::\n\n Integration points to external services (i.e. databases, queues, etc) are\n more likely to fail, so make sure to always use timeouts when accessing such\n services if there's support at the API level.\n\nIf you'd like to use the Redis backing, initialize the ``CircuitBreaker`` with\na ``CircuitRedisStorage``::\n\n import pybreaker\n import redis\n\n redis = redis.StrictRedis()\n db_breaker = pybreaker.CircuitBreaker(\n fail_max=5,\n reset_timeout=60,\n state_storage=pybreaker.CircuitRedisStorage(pybreaker.STATE_CLOSED, redis))\n\n**Do not** initialize the Redis connection with the ``decode_responses`` set to\n``True``, this will force returning ASCII objects from redis and in Python3+ will\nfail with:\n\n `AttributeError: 'str' object has no attribute 'decode'`\n\n\n.. note::\n\n You may want to reuse a connection already created in your application, if you're\n using ``django_redis`` for example::\n\n import pybreaker\n from django_redis import get_redis_connection\n\n db_breaker = pybreaker.CircuitBreaker(\n fail_max=5,\n reset_timeout=60,\n state_storage=pybreaker.CircuitRedisStorage(pybreaker.STATE_CLOSED, get_redis_connection('default')))\n\n\nEvent Listening\n```````````````\n\nThere's no need to subclass ``CircuitBreaker`` if you just want to take action\nwhen certain events occur. In that case, it's better to subclass\n``CircuitBreakerListener`` instead::\n\n class DBListener(pybreaker.CircuitBreakerListener):\n \"Listener used by circuit breakers that execute database operations.\"\n\n def before_call(self, cb, func, *args, **kwargs):\n \"Called before the circuit breaker `cb` calls `func`.\"\n pass\n\n def state_change(self, cb, old_state, new_state):\n \"Called when the circuit breaker `cb` state changes.\"\n pass\n\n def failure(self, cb, exc):\n \"Called when a function invocation raises a system error.\"\n pass\n\n def success(self, cb):\n \"Called when a function invocation succeeds.\"\n pass\n\n class LogListener(pybreaker.CircuitBreakerListener):\n \"Listener used to log circuit breaker events.\"\n\n def state_change(self, cb, old_state, new_state):\n msg = \"State Change: CB: {0}, New State: {1}\".format(cb.name, new_state)\n logging.info(msg)\n\n\nTo add listeners to a circuit breaker::\n\n # At creation time...\n db_breaker = pybreaker.CircuitBreaker(listeners=[DBListener(), LogListener()])\n\n # ...or later\n db_breaker.add_listeners(OneListener(), AnotherListener())\n\n\nWhat Does a Circuit Breaker Do?\n```````````````````````````````\n\nLet's say you want to use a circuit breaker on a function that updates a row\nin the ``customer`` database table::\n\n @db_breaker\n def update_customer(cust):\n # Do stuff here...\n pass\n\n # Will trigger the circuit breaker\n updated_customer = update_customer(my_customer)\n\n\nOr if you don't want to use the decorator syntax::\n\n def update_customer(cust):\n # Do stuff here...\n pass\n\n # Will trigger the circuit breaker\n updated_customer = db_breaker.call(update_customer, my_customer)\n\n\nAccording to the default parameters, the circuit breaker ``db_breaker`` will\nautomatically open the circuit after 5 consecutive failures in\n``update_customer``.\n\nWhen the circuit is open, all calls to ``update_customer`` will fail immediately\n(raising ``CircuitBreakerError``) without any attempt to execute the real\noperation. If you want the original error to be thrown when the circuit trips,\nset the ``throw_new_error_on_trip`` option to ``False``::\n\n pybreaker.CircuitBreaker(..., throw_new_error_on_trip=False)\n\n\nAfter 60 seconds, the circuit breaker will allow the next call to\n``update_customer`` pass through. If that call succeeds, the circuit is closed;\nif it fails, however, the circuit is opened again until another timeout elapses.\n\nBy default, when the circuit breaker trips, it w\n\nOptional Tornado Support\n````````````````````````\nA circuit breaker can (optionally) be used to call asynchronous Tornado functions::\n\n from tornado import gen\n\n @db_breaker(__pybreaker_call_async=True)\n @gen.coroutine\n def async_update(cust):\n # Do async stuff here...\n pass\n\nOr if you don't want to use the decorator syntax::\n\n @gen.coroutine\n def async_update(cust):\n # Do async stuff here...\n pass\n\n updated_customer = db_breaker.call_async(async_update, my_customer)\n\n\nExcluding Exceptions\n````````````````````\n\nBy default, a failed call is any call that raises an exception. However, it's\ncommon to raise exceptions to also indicate business exceptions, and those\nexceptions should be ignored by the circuit breaker as they don't indicate\nsystem errors::\n\n # At creation time...\n db_breaker = CircuitBreaker(exclude=[CustomerValidationError])\n\n # ...or later\n db_breaker.add_excluded_exception(CustomerValidationError)\n\n\nIn that case, when any function guarded by that circuit breaker raises\n``CustomerValidationError`` (or any exception derived from\n``CustomerValidationError``), that call won't be considered a system failure.\n\nSo as to cover cases where the exception class alone is not enough to determine\nwhether it represents a system error, you may also pass a callable rather than\na type::\n\n db_breaker = CircuitBreaker(exclude=[lambda e: type(e) == HTTPError and e.status_code < 500])\n\nYou may mix types and filter callables freely.\n\n\nMonitoring and Management\n`````````````````````````\n\nA circuit breaker provides properties and functions you can use to monitor and\nchange its current state::\n\n # Get the current number of consecutive failures\n print db_breaker.fail_counter\n\n # Get/set the maximum number of consecutive failures\n print db_breaker.fail_max\n db_breaker.fail_max = 10\n\n # Get/set the current reset timeout period (in seconds)\n print db_breaker.reset_timeout\n db_breaker.reset_timeout = 60\n\n # Get the current state, i.e., 'open', 'half-open', 'closed'\n print db_breaker.current_state\n\n # Closes the circuit\n db_breaker.close()\n\n # Half-opens the circuit\n db_breaker.half_open()\n\n # Opens the circuit\n db_breaker.open()\n\n\nThese properties and functions might and should be exposed to the operations\nstaff somehow as they help them to detect problems in the system.\n\n\nDonate\n------\n\nIf this project is useful for you, buy me a beer!\n\nBitcoin: ``bc1qtwyfcj7pssk0krn5wyfaca47caar6nk9yyc4mu``\n\n.. _Python: http://python.org\n.. _Jython: http://jython.org\n.. _Release It!: https://pragprog.com/titles/mnee2/release-it-second-edition/\n.. _PyPI: http://pypi.python.org\n.. _Git: http://git-scm.com\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/danielfm/pybreaker", "keywords": "design,pattern,circuit,breaker,integration", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "pybreaker", "package_url": "https://pypi.org/project/pybreaker/", "platform": "Any", "project_url": "https://pypi.org/project/pybreaker/", "project_urls": { "Homepage": "http://github.com/danielfm/pybreaker" }, "release_url": "https://pypi.org/project/pybreaker/0.8.0/", "requires_dist": null, "requires_python": "", "summary": "Python implementation of the Circuit Breaker pattern", "version": "0.8.0", "yanked": false, "yanked_reason": null }, "last_serial": 13062811, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "9cb2a57df07e3f6d480304b2e7893f83", "sha256": "3039cadf10a06129f1fe0d8bd98a7d8d2c4c07a993030fed1067e6436db251f1" }, "downloads": -1, "filename": "pybreaker-0.1.1.tar.gz", "has_sig": false, "md5_digest": "9cb2a57df07e3f6d480304b2e7893f83", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14415, "upload_time": "2010-10-18T03:34:52", "upload_time_iso_8601": "2010-10-18T03:34:52.595980Z", "url": "https://files.pythonhosted.org/packages/b1/d2/b28f2e47ddd7694a7a97b683bb1de9feca153ad223023adc9f8eb10f57b8/pybreaker-0.1.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2": [ { "comment_text": "", "digests": { "md5": "2bf38fd6364482bc5c2a7c085fb5a656", "sha256": "0fa5bb539ff256ace3d5284fd82d1b0ac40e708f6fc4b919911bc1301771ac87" }, "downloads": -1, "filename": "pybreaker-0.2.tar.gz", "has_sig": false, "md5_digest": "2bf38fd6364482bc5c2a7c085fb5a656", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15425, "upload_time": "2010-10-20T17:22:46", "upload_time_iso_8601": "2010-10-20T17:22:46.292563Z", "url": "https://files.pythonhosted.org/packages/42/96/d236e72831a43a360ec35e85d8a7467317b756cd685d8810fa6b4b626b65/pybreaker-0.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "7ec1ba3d3926fbdb0fe131ded62af82a", "sha256": "fe66577062e7610b3c41de7dffae9fad9fc405c4a23ff4e61caefd497e042ad8" }, "downloads": -1, "filename": "pybreaker-0.2.1.tar.gz", "has_sig": false, "md5_digest": "7ec1ba3d3926fbdb0fe131ded62af82a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16014, "upload_time": "2010-10-23T18:23:34", "upload_time_iso_8601": "2010-10-23T18:23:34.376586Z", "url": "https://files.pythonhosted.org/packages/1e/7c/87b013d93515f123e36c096838be59e193cee50a17e791e67d140b456ca2/pybreaker-0.2.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "e6a8abcbef85d2813293a0418a5df5ce", "sha256": "514a597e27ec464e65e39fc7a7728a0a163cb3d1a9c9b2cb913775398b132b51" }, "downloads": -1, "filename": "pybreaker-0.2.2-py2.6.egg", "has_sig": false, "md5_digest": "e6a8abcbef85d2813293a0418a5df5ce", "packagetype": "bdist_egg", "python_version": "2.6", "requires_python": null, "size": 11682, "upload_time": "2012-09-27T19:20:13", "upload_time_iso_8601": "2012-09-27T19:20:13.196937Z", "url": "https://files.pythonhosted.org/packages/e7/af/abddb720d7d94e1887a53b90d30f317434f99c1c225c7df23f492a5c54a7/pybreaker-0.2.2-py2.6.egg", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "78213cff35001612e04eb70fe8dfb765", "sha256": "ef95f1503a220bb9ce8c5bcb7bdef98de01c4551038344ab0c67adff9ef6e214" }, "downloads": -1, "filename": "pybreaker-0.2.2-py2.7.egg", "has_sig": false, "md5_digest": "78213cff35001612e04eb70fe8dfb765", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 11637, "upload_time": "2012-09-27T19:20:32", "upload_time_iso_8601": "2012-09-27T19:20:32.172845Z", "url": "https://files.pythonhosted.org/packages/c3/3a/e3aac21ee72b233d3f2fff67241a76f0744708143f78d71db2093724e8da/pybreaker-0.2.2-py2.7.egg", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "af3dd7d332783744eb6e0ce0f24b8cc6", "sha256": "d1f2842f519ffbfbe3571de0c3760afa455a799aecc29665ef1d47407c41a1e9" }, "downloads": -1, "filename": "pybreaker-0.2.2-py3.2.egg", "has_sig": false, "md5_digest": "af3dd7d332783744eb6e0ce0f24b8cc6", "packagetype": "bdist_egg", "python_version": "3.2", "requires_python": null, "size": 11764, "upload_time": "2012-09-27T19:21:02", "upload_time_iso_8601": "2012-09-27T19:21:02.888337Z", "url": "https://files.pythonhosted.org/packages/5e/8e/03dc2f8ba7ff90b25cfacc8df59ef2d9c9697fcfc11fe7393fd548febe82/pybreaker-0.2.2-py3.2.egg", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "39b5b54b25fbdca075b28a08d086d5db", "sha256": "c36612988753d56a0c1485b03022ba9990b73c32187d6c685d17fd2e03792be9" }, "downloads": -1, "filename": "pybreaker-0.2.2.tar.gz", "has_sig": false, "md5_digest": "39b5b54b25fbdca075b28a08d086d5db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7237, "upload_time": "2012-09-27T19:19:45", "upload_time_iso_8601": "2012-09-27T19:19:45.424882Z", "url": "https://files.pythonhosted.org/packages/b8/2f/7adcc986f943d7a4457cd5a2ae94f74f326840b798911856ae1e6bce3712/pybreaker-0.2.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "813f42a4fe2eb1e7790307fc51bf64b4", "sha256": "762b6b080f1d1735ed8a8b9ced5595b88a7fcfce550ab2da3e501051b5c95904" }, "downloads": -1, "filename": "pybreaker-0.2.3.tar.gz", "has_sig": false, "md5_digest": "813f42a4fe2eb1e7790307fc51bf64b4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6633, "upload_time": "2014-07-25T18:04:17", "upload_time_iso_8601": "2014-07-25T18:04:17.862109Z", "url": "https://files.pythonhosted.org/packages/ab/21/a58aec83d9695f23a779c14283feaa5de714e763b55c16731f80e6b5a9cc/pybreaker-0.2.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "11941e9be32a1d14b9ee32c87761d0a1", "sha256": "8d7af4e669dd1dbf59b3d00eb125bff65d5dd511df2133a4ab40b07447623ab0" }, "downloads": -1, "filename": "pybreaker-0.3.0.tar.gz", "has_sig": false, "md5_digest": "11941e9be32a1d14b9ee32c87761d0a1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6652, "upload_time": "2016-09-01T18:54:01", "upload_time_iso_8601": "2016-09-01T18:54:01.837909Z", "url": "https://files.pythonhosted.org/packages/b9/69/8287919f2aedae931456cf74fda6e8d23936f54e817052b8f7982888a937/pybreaker-0.3.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "185eaa3caff6c1f8ff474a70f9668586", "sha256": "fe1e29d58ddd3291140eb3ee6b3c18f6ad558d2b55ce82470ce808fced0d62a9" }, "downloads": -1, "filename": "pybreaker-0.3.1.tar.gz", "has_sig": false, "md5_digest": "185eaa3caff6c1f8ff474a70f9668586", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6748, "upload_time": "2017-01-25T21:12:31", "upload_time_iso_8601": "2017-01-25T21:12:31.003779Z", "url": "https://files.pythonhosted.org/packages/15/f7/0208f3ffb3ea6ddda18b43dd2c0495326f5c6bf1c83fa93c44539ad8f0ca/pybreaker-0.3.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "32ed7dd86b4ae7a66419445d2a507905", "sha256": "2654f3701a40c69e4133b5421445489e171fe6804863d306f8e395a8fb8f6f4a" }, "downloads": -1, "filename": "pybreaker-0.3.2.tar.gz", "has_sig": false, "md5_digest": "32ed7dd86b4ae7a66419445d2a507905", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8459, "upload_time": "2017-06-01T14:45:04", "upload_time_iso_8601": "2017-06-01T14:45:04.437615Z", "url": "https://files.pythonhosted.org/packages/4e/aa/7b0c3cf7a4ebca449dd42acd4c74ff207661227d80efe3f053cd21291db4/pybreaker-0.3.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "c22a1c47c0e430f2377d61a5d732f00e", "sha256": "18cca0f7f2293b4202f0e3882f543208d971b8538a011fb64091f1a893485cce" }, "downloads": -1, "filename": "pybreaker-0.3.3.tar.gz", "has_sig": false, "md5_digest": "c22a1c47c0e430f2377d61a5d732f00e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8616, "upload_time": "2017-06-02T13:20:21", "upload_time_iso_8601": "2017-06-02T13:20:21.008808Z", "url": "https://files.pythonhosted.org/packages/12/8d/0e19396f6b71327dbd5eae7fa6f0a4b886c34d8d2bfc854d4f223c61e6ec/pybreaker-0.3.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "0aad7be6dd10da0301cd657306d961f0", "sha256": "923b60065bf1b14df58fd7cffcca04de7e605e301cf163a2f0c2ce507b1f75c2" }, "downloads": -1, "filename": "pybreaker-0.4.0.tar.gz", "has_sig": false, "md5_digest": "0aad7be6dd10da0301cd657306d961f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9146, "upload_time": "2017-06-23T14:33:21", "upload_time_iso_8601": "2017-06-23T14:33:21.118592Z", "url": "https://files.pythonhosted.org/packages/ad/b1/b9c6e27c52899a503420cf335ce19d5e4024d72c7081aff87f21ce750c45/pybreaker-0.4.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "26d61001fc193a267cbfefa9499586a2", "sha256": "c4ed5d2499d4b9a030e675ab458b68f7cf9dd324891d77258a16a9f39ed926ef" }, "downloads": -1, "filename": "pybreaker-0.4.1.tar.gz", "has_sig": false, "md5_digest": "26d61001fc193a267cbfefa9499586a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9467, "upload_time": "2017-10-02T17:09:45", "upload_time_iso_8601": "2017-10-02T17:09:45.081926Z", "url": "https://files.pythonhosted.org/packages/f6/36/eba7b5d8c113724d607f37a69a764eae72324749da870ae8f62792ec4e94/pybreaker-0.4.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "fa550f72bd38f489b0a5d60a6b4c2b27", "sha256": "f1167038a31ebb841bc821de5afa5fa84d960a1d1caf7aeb0f97e217cd819662" }, "downloads": -1, "filename": "pybreaker-0.4.2.tar.gz", "has_sig": false, "md5_digest": "fa550f72bd38f489b0a5d60a6b4c2b27", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9690, "upload_time": "2017-11-09T16:28:58", "upload_time_iso_8601": "2017-11-09T16:28:58.082787Z", "url": "https://files.pythonhosted.org/packages/3e/78/e291f6ed115e7d396e6a501c3398ce32e5a0d26cdf307d9bb5de98525d44/pybreaker-0.4.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "bb30611c11f0dc417759c860e7aa4bde", "sha256": "c034de4e8d0501bda05dcab21e08f43a4956cf59c1605c8b8d1504ad790d5aa9" }, "downloads": -1, "filename": "pybreaker-0.4.4.tar.gz", "has_sig": false, "md5_digest": "bb30611c11f0dc417759c860e7aa4bde", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12396, "upload_time": "2018-05-21T13:56:45", "upload_time_iso_8601": "2018-05-21T13:56:45.235071Z", "url": "https://files.pythonhosted.org/packages/40/d5/ffacc5b20376c0d0a677f597817cfd603ad195cb47223c1ab5db414f4335/pybreaker-0.4.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.5": [ { "comment_text": "", "digests": { "md5": "f7a53730b699e5a052883395236de3b7", "sha256": "71856aa75de7365088baa452a5bbac6845f19c93f28391a0799c17658a4b3089" }, "downloads": -1, "filename": "pybreaker-0.4.5.tar.gz", "has_sig": false, "md5_digest": "f7a53730b699e5a052883395236de3b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12401, "upload_time": "2018-10-26T18:21:37", "upload_time_iso_8601": "2018-10-26T18:21:37.816954Z", "url": "https://files.pythonhosted.org/packages/5e/15/d3d120022aab24bbfb22a1eae479592d62dcece7188d5d3fcc590f587ccc/pybreaker-0.4.5.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "a9297acdd138ba9f1a4c0d6ef76a7193", "sha256": "53e1d532e6d8924646cafbdffabfc3d383ada7a6d7ef6d5a01aad7eb4ad1742f" }, "downloads": -1, "filename": "pybreaker-0.5.0.tar.gz", "has_sig": false, "md5_digest": "a9297acdd138ba9f1a4c0d6ef76a7193", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10259, "upload_time": "2019-03-19T15:26:29", "upload_time_iso_8601": "2019-03-19T15:26:29.789666Z", "url": "https://files.pythonhosted.org/packages/be/b7/a520f2ea910149249acb99b7ae316610fde8bb8f4c1e3181cf4d1de86652/pybreaker-0.5.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "9997190966ea8be7e271af87433ea136", "sha256": "038c2808d4f845bf7e17819ad278aa5701c6512a5e389760bc4657be0a5364d3" }, "downloads": -1, "filename": "pybreaker-0.6.0.tar.gz", "has_sig": false, "md5_digest": "9997190966ea8be7e271af87433ea136", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10266, "upload_time": "2019-10-22T15:01:05", "upload_time_iso_8601": "2019-10-22T15:01:05.477725Z", "url": "https://files.pythonhosted.org/packages/1d/c7/33834aa826b086fd69e6f017d988d9d4c96fa2adffcf5cf5a47cf59ee061/pybreaker-0.6.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "b5090fbe0c2de989e959914aa8df601c", "sha256": "31aa800c2bc80e89ab42480decea556a920b59e15451857995387a0ee09a8d41" }, "downloads": -1, "filename": "pybreaker-0.7.0.tar.gz", "has_sig": false, "md5_digest": "b5090fbe0c2de989e959914aa8df601c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11126, "upload_time": "2021-12-14T15:13:53", "upload_time_iso_8601": "2021-12-14T15:13:53.751058Z", "url": "https://files.pythonhosted.org/packages/75/e5/0b7ebc6748593f9643758e4d1b41bbf3f261f074ac0952b159a289cd8270/pybreaker-0.7.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "b40d38d5920c37e79dc9c85c7ef267f0", "sha256": "41d51901a5a69e78761f1a2abdc0ae25a82c58eb752977c7b4eec51330095efc" }, "downloads": -1, "filename": "pybreaker-0.8.0.tar.gz", "has_sig": false, "md5_digest": "b40d38d5920c37e79dc9c85c7ef267f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11121, "upload_time": "2022-03-02T23:18:44", "upload_time_iso_8601": "2022-03-02T23:18:44.672029Z", "url": "https://files.pythonhosted.org/packages/ea/2e/8f6cafaed265acb12f6c7f870496e75d02e11f83ed213f1b4976a27af7b9/pybreaker-0.8.0.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b40d38d5920c37e79dc9c85c7ef267f0", "sha256": "41d51901a5a69e78761f1a2abdc0ae25a82c58eb752977c7b4eec51330095efc" }, "downloads": -1, "filename": "pybreaker-0.8.0.tar.gz", "has_sig": false, "md5_digest": "b40d38d5920c37e79dc9c85c7ef267f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11121, "upload_time": "2022-03-02T23:18:44", "upload_time_iso_8601": "2022-03-02T23:18:44.672029Z", "url": "https://files.pythonhosted.org/packages/ea/2e/8f6cafaed265acb12f6c7f870496e75d02e11f83ed213f1b4976a27af7b9/pybreaker-0.8.0.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }