{ "info": { "author": "Sam McCormack", "author_email": "contact@cabbagedevelopment.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8" ], "description": "# Async Process Scheduler\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![PyPI](https://img.shields.io/pypi/v/AsyncProcessScheduler)](https://pypi.org/project/AsyncProcessScheduler)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/AsyncProcessScheduler)\n[![Build Status](https://travis-ci.org/CabbageDevelopment/async-process-scheduler.svg?branch=master)](https://travis-ci.org/CabbageDevelopment/async-process-scheduler)\n\n*Current status: beta. Breaking changes may occur before v1.0.0.*\n\n## Introduction\n\nAsync Process Scheduler is a small Python library which provides a simple, GUI-friendly way to efficiently run many processes while avoiding a callback-based data flow.\n\nAsync Process Scheduler is compatible with `multiprocessing` from the standard library, and equivalent implementations such as `multiprocess`.\n\n> **Note:** To use Async Process Scheduler in a GUI program, you'll need a library which implements a compatible event loop. For example, [qasync](https://github.com/CabbageDevelopment/qasync) can be used with PyQt5.\n\n## Installation\n\nTo install Async Process Scheduler, use `pip`:\n\n```bash\npip install AsyncProcessScheduler\n```\n\n## Example\n\nDetailed examples are in the [examples](/examples) folder, including a [GUI example](/examples/gui/gui.py) using PyQt5. Here is a code snippet which shows the general workflow:\n\n```python\nfrom scheduler.Scheduler import Scheduler\n\ndef long_calculation(x: int, y: int) -> Tuple[int, int]:\n \"\"\"Simulates a long calculation and returns two numbers.\"\"\"\n time.sleep(5)\n return x, y\n\nasync def run() -> None:\n \"\"\"Runs 16 processes with the scheduler and prints the results.\"\"\"\n scheduler = Scheduler()\n\n # Create (x, y) inputs for 16 processes.\n num_processes = 16\n args = [(i, i+1) for i in range(num_processes)]\n\n # Run all processes and get an ordered list containing the results from each.\n results: List[Tuple] = await scheduler.map(target=long_calculation, args=args)\n\n # Do something with the results.\n print(results)\n\n# Start the coroutine (blocking to prevent the program from exiting).\nloop = asyncio.get_event_loop() \nloop.run_until_complete(run())\n```\n\n> **Note:** GUI programs would use `asyncio.ensure_future(run())` to start the coroutine without blocking.\n\n## Quick guide\n\nThis guide explains the basic usage of Async Process Scheduler.\n\n### Importing Scheduler\n\nTo use `Scheduler` in Python, import from `scheduler`:\n\n```python\nfrom scheduler.Scheduler import Scheduler\n```\n\n### Creating a scheduler\n\nScheduler instances can be created with or without a progress callback. The progress callback is a function which takes the number of tasks completed and the total number of tasks. \n\n```python\ndef on_progress(finished: int, total: int) -> None:\n print(f\"{finished} of {total} tasks are complete.\")\n\n# Without progress callback.\nscheduler = Scheduler()\n\n# With progress callback.\nscheduler = Scheduler(on_progress)\n\n# With progress callback.\nscheduler = Scheduler(progress_callback=on_progress)\n```\n\nThe progress callback is called on the thread which the coroutine runs in, and can be used to modify the GUI.\n\n> :warning: This functionality may change before v1.0.0.\n\n### Mapping using a scheduler\n\nThe easiest way to run code using a Scheduler is to map an iterable of inputs over a function. \n\nThis allows you to supply a function, and a list of tuples containing the inputs to the function. The output will be calculated in a separate process for each set of inputs.\n\n#### Mapping in a coroutine\n\n```python\n\"\"\"\nSnippet which demonstrates mapping values over a function.\n\"\"\"\n\ndef my_calculation(x: int, y: float, z: str) -> Tuple[int, float, str]:\n \"\"\"Simulates a long calculation and returns the function parameters.\"\"\"\n time.sleep(5)\n return x, y, z\n\nscheduler = Scheduler()\nargs = [\n (1, 3.14, \"test1\"), # Args for first process.\n (0, 2.10, \"test2\"), # Args for second process.\n (5, 10.0, \"test3\"), # Args for third process.\n]\n```\n\nThe results can then be computed in a coroutine:\n\n```python\nresults: List = await scheduler.map(target=my_calculation, args=args)\n```\n\n#### Mapping (blocking)\n\n```python\nresults: List = scheduler.map_blocking(target=my_calculation, args=args)\n```\n\n### Adding tasks to a scheduler\n\nInstead of using `map()`, tasks can individually be added to a scheduler. After adding all tasks, the scheduler can be started with `run()`.\n\nYou can add normal functions to a scheduler. If you're migrating from process-oriented code, you may find it easier to add processes and queues to a scheduler instead.\n\nEvery task added to a scheduler will be run as a separate process. For maximum efficiency, you should aim to add a number of tasks greater than the number of logical cores. The optimal number for the current CPU is returned by the static method `Scheduler.optimal_process_count()`.\n\nFor simplicity, the examples below only add one task to the scheduler.\n\n#### Adding functions\n\n`add()` can be used to add a function to the scheduler. `add()` is similar to the constructor of `Process`.\n\n```python\n\"\"\"\nSnippet which demonstrates adding functions to a scheduler.\n\"\"\"\n\ndef my_calculation(x: int, y: float, z: str) -> Tuple[int, float, str]:\n \"\"\"Simulates a long calculation and returns the function parameters.\"\"\"\n time.sleep(5)\n return x, y, z\n\nscheduler = Scheduler()\nargs = (1, 3.14, \"test\",)\n\n# Without named arguments.\nscheduler.add(my_calculation, args)\n\n# With named arguments.\nscheduler.add(target=my_calculation, args=args)\n```\n\nInternally, `add()` creates a process and queue which will be used to run your function and get the results. To use types other than those from `multiprocessing`, you can specify them with the `process_type` and `queue_type` arguments.\n\n```python\n\"\"\"\nSnippet which demonstrates adding a function to scheduler using Processes and Queues\nfrom `multiprocess` instead of `multiprocessing`.\n\"\"\"\nfrom multiprocess import Process, Queue\n\nscheduler = Scheduler()\nscheduler.add(\n target=my_function,\n args=(1,2,3,),\n process_type=Process,\n queue_type=Queue\n)\n```\n\n#### Adding processes\n\n`add_process()` can be used to add a process and queue to the scheduler.\n\n```python\n\"\"\"\nSnippet which demonstrates adding processes and queues to a scheduler.\n\"\"\"\n\ndef my_calculation(queue: Queue, x: int, y: int) -> None:\n \"\"\"Function which will be run using a process.\"\"\"\n time.sleep(5)\n\n # Important: put results in queue instead of returning them.\n queue.put((\n x, y\n ))\n\nscheduler = Scheduler()\n\nqueue = Queue()\nprocess = Process(target=my_calculation, args=(queue, 1, 2))\n\nscheduler.add_process(process, queue)\n```\n\n> :warning: When adding processes, ensure that the queue instance passed to the function is the same as the queue added to the scheduler. Also take care that the function puts its output in the queue instead of returning it.\n\n#### Sub-tasks\n\nThe functions above take an optional `subtasks` parameter. `subtasks` is used to hint to the scheduler that each process may create its own processes; this will be taken into account when scheduling processes.\n\nFor example, if each process creates 4 processes you could use `scheduler.add(target=my_process, args=my_args, subtasks=4)`.\n\n### Running a scheduler\n\nWhen a scheduler runs, it will run all tasks until complete and then return an ordered list containing the output from each task.\n\n#### Running in a coroutine\n\n```python\nresults: List = await scheduler.run()\n```\n\n#### Running (blocking)\n\n```python\nresults: List = scheduler.run_blocking()\n```\n\n### Terminating a scheduler\n\nTo cancel a scheduler, use `terminate()`:\n\n```python\nscheduler.terminate()\n```\n\nA terminated scheduler will always return an empty list.\n\n## Design\n\nWhen the scheduler starts, it will simultaneously run a number of processes up to the value returned by `Scheduler.optimal_process_count()`. When a process finishes, another is started to take its place.\n\nIf `dynamic` is enabled, the scheduler will check the CPU usage periodically and increase the number of concurrent processes if the CPU usage is below the threshold.\n\nThis diagram demonstrates the implementation of `Scheduler`:\n\n![Image demonstrating the implementation of Scheduler.](/docs/images/scheduler.png)\n\n## Developer notes\n\n### Packaging the project\n\nFrom the [documentation](https://packaging.python.org/guides/distributing-packages-using-setuptools/#packaging-your-project):\n\n```\nrm -r dist/\npython setup.py sdist\npython setup.py bdist_wheel\ntwine upload dist/*\n```\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/CabbageDevelopment/async-process-scheduler", "keywords": "async asyncio processing multiprocessing scheduler scheduling processes coroutines gui", "license": "", "maintainer": "", "maintainer_email": "", "name": "AsyncProcessScheduler", "package_url": "https://pypi.org/project/AsyncProcessScheduler/", "platform": "", "project_url": "https://pypi.org/project/AsyncProcessScheduler/", "project_urls": { "Homepage": "https://github.com/CabbageDevelopment/async-process-scheduler", "Source": "https://github.com/CabbageDevelopment/async-process-scheduler" }, "release_url": "https://pypi.org/project/AsyncProcessScheduler/0.9.0b1/", "requires_dist": [ "psutil" ], "requires_python": "~=3.6", "summary": "GUI-friendly library for scheduling processes using coroutines.", "version": "0.9.0b1", "yanked": false, "yanked_reason": null }, "last_serial": 7234515, "releases": { "0.1.0b1": [ { "comment_text": "", "digests": { "md5": "1a109810a4295e9e86e9f10729c1eabe", "sha256": "ae1bbf589f9ca79b365a34a8047ac8225ee292e4cd9fc25b8b24eef76e47942e" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.1.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "1a109810a4295e9e86e9f10729c1eabe", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 9321, "upload_time": "2019-10-20T17:01:05", "upload_time_iso_8601": "2019-10-20T17:01:05.714786Z", "url": "https://files.pythonhosted.org/packages/51/b9/2da80195f8fe34a1b95bd89526c14b87a87ae12d5ed22288c61f3150b1a1/AsyncProcessScheduler-0.1.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "f334f815875a2f59b02b8ce810059fd2", "sha256": "9c78e4f092907a093ece6abe937ebc1dcb4e7d6a27d7cb67d57353aa90597c98" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.1.0b1.tar.gz", "has_sig": false, "md5_digest": "f334f815875a2f59b02b8ce810059fd2", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 5725, "upload_time": "2019-10-20T17:01:08", "upload_time_iso_8601": "2019-10-20T17:01:08.478789Z", "url": "https://files.pythonhosted.org/packages/5c/08/bbf230bbdf4db30e79ca25aa6e753c5974f1cddfe46004e4e3d86fd9c040/AsyncProcessScheduler-0.1.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.0b1": [ { "comment_text": "", "digests": { "md5": "853e1f4b20765ae3808c3ebdec0b94c0", "sha256": "cd2cd58ee6d77918d9b5ff6d7ae9e7cf7bcdcece3a9956f6e83884811b85c81e" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.2.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "853e1f4b20765ae3808c3ebdec0b94c0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 9650, "upload_time": "2019-10-24T07:41:10", "upload_time_iso_8601": "2019-10-24T07:41:10.128362Z", "url": "https://files.pythonhosted.org/packages/34/8c/6d6d2179f6b7654e6838e1e4ae47e856c5fd8c4c3f95048f08a8ffa086aa/AsyncProcessScheduler-0.2.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "4794d2a428798d5e7c8a0e58b6436f26", "sha256": "675b8aeeb0c4c378516d9af8fe037757d0fdde29207baa0bd3990e2fad7b409b" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.2.0b1.tar.gz", "has_sig": false, "md5_digest": "4794d2a428798d5e7c8a0e58b6436f26", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 6413, "upload_time": "2019-10-24T07:41:11", "upload_time_iso_8601": "2019-10-24T07:41:11.670023Z", "url": "https://files.pythonhosted.org/packages/87/78/c9f70192a37e9b4b39a7433910073f2340f05aa482f0ccc1122decd176e1/AsyncProcessScheduler-0.2.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.0b1": [ { "comment_text": "", "digests": { "md5": "9cec71ac27743716ac858a509500f718", "sha256": "697056287fd02e401f506c3623552426e4a362fc495e861e39b80aaafb65330d" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.3.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "9cec71ac27743716ac858a509500f718", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 9982, "upload_time": "2019-10-26T11:40:15", "upload_time_iso_8601": "2019-10-26T11:40:15.754842Z", "url": "https://files.pythonhosted.org/packages/68/6e/1e8b1d900905dbab38ea02b220bdca203cae88ca8893f0769c27f743877c/AsyncProcessScheduler-0.3.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "a22c4f31c0bc0edb9a95fca8b1c581ad", "sha256": "fc44e27cc89c7eec962209dc6f8fd276d1a2e5097d28b6c33c7d8df37eb9b55b" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.3.0b1.tar.gz", "has_sig": false, "md5_digest": "a22c4f31c0bc0edb9a95fca8b1c581ad", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 7095, "upload_time": "2019-10-26T11:40:17", "upload_time_iso_8601": "2019-10-26T11:40:17.384021Z", "url": "https://files.pythonhosted.org/packages/29/f7/1afd4c145847af72b064ccacbfe8e775ababcec3994c0c96151480b2bbb9/AsyncProcessScheduler-0.3.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.0b1": [ { "comment_text": "", "digests": { "md5": "e35e24758eb2bec34c6a268c105a2ea4", "sha256": "7f4bbc335f2d98db10f8d4000d39d7f7ef961615a513c8037d50a08ac0843dac" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.4.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "e35e24758eb2bec34c6a268c105a2ea4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 11715, "upload_time": "2019-11-03T14:51:56", "upload_time_iso_8601": "2019-11-03T14:51:56.640136Z", "url": "https://files.pythonhosted.org/packages/5c/69/4d31e385adbfffbbf0c46729640ad91013d94a9985ee50c39a25b2a861a8/AsyncProcessScheduler-0.4.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "7eea714dfbb69007d7f3f301f4d5fbfc", "sha256": "0ae97198bc5a3fdfa13fc0b10d120fd0e422f4906bab7b939a8c678c85a59a55" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.4.0b1.tar.gz", "has_sig": false, "md5_digest": "7eea714dfbb69007d7f3f301f4d5fbfc", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 9284, "upload_time": "2019-11-03T14:51:58", "upload_time_iso_8601": "2019-11-03T14:51:58.238879Z", "url": "https://files.pythonhosted.org/packages/22/f0/943d482595824cd78d2bdbdfbf65614bb3706e3a070eefed1017bb09be77/AsyncProcessScheduler-0.4.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.5.0b1": [ { "comment_text": "", "digests": { "md5": "8409eb7b13575286b7b9afab51cb06e3", "sha256": "4eb56da31b3c2ebf7d9b6dc217c6b9b07fc7f28e35f3cf51076c8db98bbd4bb5" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.5.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "8409eb7b13575286b7b9afab51cb06e3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 13475, "upload_time": "2020-02-26T16:39:02", "upload_time_iso_8601": "2020-02-26T16:39:02.246534Z", "url": "https://files.pythonhosted.org/packages/94/65/0a5940a9cc07d76d8318d85c1c79aecd4b6227759b19c13832bd29397cee/AsyncProcessScheduler-0.5.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "1dd5db63546ab2ad59dbb686dcfc747b", "sha256": "3fb100a0848ea06e1110df7a5da2c67ab3baa2abfed03d7c18f8540857bd37c8" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.5.0b1.tar.gz", "has_sig": false, "md5_digest": "1dd5db63546ab2ad59dbb686dcfc747b", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 11508, "upload_time": "2020-02-26T16:39:04", "upload_time_iso_8601": "2020-02-26T16:39:04.262798Z", "url": "https://files.pythonhosted.org/packages/73/48/ff2eebb0ccc8f6778d3604322b1576381831ab3e5067f877c97f879d962f/AsyncProcessScheduler-0.5.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.6.0b1": [ { "comment_text": "", "digests": { "md5": "6df33a12bfed4dfa09d91ef6f7f628b7", "sha256": "7045eaf9d9d43bba50715aa1bb45594bfda1fc26e44e06208cab8f259baf4655" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.6.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "6df33a12bfed4dfa09d91ef6f7f628b7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 15830, "upload_time": "2020-04-01T19:10:29", "upload_time_iso_8601": "2020-04-01T19:10:29.464949Z", "url": "https://files.pythonhosted.org/packages/0f/5c/4c6659f3ccd9c8e6be76f89551f48d62f03838ff77b8250b8f1da62aa96b/AsyncProcessScheduler-0.6.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "bfba13852f82d7f822bca11029dddf56", "sha256": "7f37d197cf11f8d19a294179a37f2a025b27cf697aadb0741722d5f0a6e85bc6" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.6.0b1.tar.gz", "has_sig": false, "md5_digest": "bfba13852f82d7f822bca11029dddf56", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 11814, "upload_time": "2020-04-01T19:10:30", "upload_time_iso_8601": "2020-04-01T19:10:30.965585Z", "url": "https://files.pythonhosted.org/packages/05/8d/599826a21ba46bf16bcf7e89b87038fe41b1ce63a2bd035873c01de5e2c5/AsyncProcessScheduler-0.6.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.7.0b1": [ { "comment_text": "", "digests": { "md5": "7823dbb59660e0c70857701d0b2b894c", "sha256": "b77bd8c340bcd4e7b16af8954dd538ad5c93c792674aa4989b99768e10ae7532" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.7.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "7823dbb59660e0c70857701d0b2b894c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 16469, "upload_time": "2020-05-05T13:48:28", "upload_time_iso_8601": "2020-05-05T13:48:28.123546Z", "url": "https://files.pythonhosted.org/packages/53/f1/8dbf2f15deb583273950aa13849c72b44f3afe3bee827e9f565db7b1c02e/AsyncProcessScheduler-0.7.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "079c387b66e5bbc82581e05dbb69eba8", "sha256": "3c6be4a69b8d348c3de6d240cc097235217bfd4e60e177c802432a572156e6e2" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.7.0b1.tar.gz", "has_sig": false, "md5_digest": "079c387b66e5bbc82581e05dbb69eba8", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 12621, "upload_time": "2020-05-05T13:48:29", "upload_time_iso_8601": "2020-05-05T13:48:29.645108Z", "url": "https://files.pythonhosted.org/packages/36/c6/cf9007ca2661cf6fd3de7b1d29f458a257f0ab29b05a177ac42de99fdb37/AsyncProcessScheduler-0.7.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.8.0b1": [ { "comment_text": "", "digests": { "md5": "9c76fbbea97c25ace4fea12136c8aaa1", "sha256": "6c2bf57967816838655a1714d6feb314b54b54af1333a1f1fbbf6087b50f62b7" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.8.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "9c76fbbea97c25ace4fea12136c8aaa1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 17172, "upload_time": "2020-05-07T12:20:08", "upload_time_iso_8601": "2020-05-07T12:20:08.591035Z", "url": "https://files.pythonhosted.org/packages/34/4b/2eac64b6815cc244f0a36c9e9a0a413fe786392c80d97f461cfbf9fef3c8/AsyncProcessScheduler-0.8.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "ee8ae395af88f5c326f2dd1275aa01bc", "sha256": "80e2696f92b4e51d0d0191eb183eaaaee3a2c18c8cd5a3a5dcc341603c5d1aea" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.8.0b1.tar.gz", "has_sig": false, "md5_digest": "ee8ae395af88f5c326f2dd1275aa01bc", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 13337, "upload_time": "2020-05-07T12:20:09", "upload_time_iso_8601": "2020-05-07T12:20:09.846310Z", "url": "https://files.pythonhosted.org/packages/b7/3f/48423928b512d854ad1259112559a4d7abc6cef46a1f7d01aa04dde970f4/AsyncProcessScheduler-0.8.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.9.0b1": [ { "comment_text": "", "digests": { "md5": "e7316172f0ff710f8bc70fb05e3c8c33", "sha256": "be0b81a2594d5babd34eb68deb9cd64884e75979a9e43fabc149302bfb9c2f19" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.9.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "e7316172f0ff710f8bc70fb05e3c8c33", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 17331, "upload_time": "2020-05-13T18:41:21", "upload_time_iso_8601": "2020-05-13T18:41:21.206926Z", "url": "https://files.pythonhosted.org/packages/63/2c/fd85ec6e5377f4945aa3197254f1f9492098a97b53215528372e6426eeab/AsyncProcessScheduler-0.9.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "3fd5dcfb587cc57e14f073d1fff1333d", "sha256": "1f2bfe90a84f2ce642d62d6e9ef8aeb9773122f1b955b7251419e1b17734e429" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.9.0b1.tar.gz", "has_sig": false, "md5_digest": "3fd5dcfb587cc57e14f073d1fff1333d", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 13483, "upload_time": "2020-05-13T18:41:22", "upload_time_iso_8601": "2020-05-13T18:41:22.809360Z", "url": "https://files.pythonhosted.org/packages/9e/77/4e155eeaeb38f31efce1473a23bd3c256233d4f394b85eb2d71e1290c88a/AsyncProcessScheduler-0.9.0b1.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e7316172f0ff710f8bc70fb05e3c8c33", "sha256": "be0b81a2594d5babd34eb68deb9cd64884e75979a9e43fabc149302bfb9c2f19" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.9.0b1-py3-none-any.whl", "has_sig": false, "md5_digest": "e7316172f0ff710f8bc70fb05e3c8c33", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 17331, "upload_time": "2020-05-13T18:41:21", "upload_time_iso_8601": "2020-05-13T18:41:21.206926Z", "url": "https://files.pythonhosted.org/packages/63/2c/fd85ec6e5377f4945aa3197254f1f9492098a97b53215528372e6426eeab/AsyncProcessScheduler-0.9.0b1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "3fd5dcfb587cc57e14f073d1fff1333d", "sha256": "1f2bfe90a84f2ce642d62d6e9ef8aeb9773122f1b955b7251419e1b17734e429" }, "downloads": -1, "filename": "AsyncProcessScheduler-0.9.0b1.tar.gz", "has_sig": false, "md5_digest": "3fd5dcfb587cc57e14f073d1fff1333d", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 13483, "upload_time": "2020-05-13T18:41:22", "upload_time_iso_8601": "2020-05-13T18:41:22.809360Z", "url": "https://files.pythonhosted.org/packages/9e/77/4e155eeaeb38f31efce1473a23bd3c256233d4f394b85eb2d71e1290c88a/AsyncProcessScheduler-0.9.0b1.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }