dm-launchpad-nightly


Namedm-launchpad-nightly JSON
Version 0.3.0.dev20210617 PyPI version JSON
download
home_pagehttps://github.com/deepmind/launchpad
SummaryLaunchpad is a library that simplifies writing distributed programs and seamlessly launching them on a range of supported platforms.
upload_time2021-06-17 10:21:34
maintainer
docs_urlNone
authorDeepMind
requires_python>=3
licenseApache 2.0
keywords deepmind reinforcement learning machine distributed
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Launchpad
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dm-launchpad)
[![PyPI version](https://badge.fury.io/py/dm-launchpad.svg)](https://badge.fury.io/py/dm-launchpad)

Launchpad is a library that simplifies writing distributed programs by
seamlessly launching them on a variety of different platforms. Switching between
local and distributed execution requires only a flag change.

Launchpad introduces a programming model that represents a distributed system
as a graph data structure (a **Program**) describing the system’s topology.
Each node in the program graph represents a service in the distributed system,
i.e. the fundamental unit of computation that we are interested in running.
As nodes are added to this graph, Launchpad constructs a handle for each of them.
A handle ultimately represents a client to the yet-to-be-constructed service.
A directed edge in the program graph, representing communication between
two services, is created when the handle associated with one node is given
to another at construction time. This edge originates from the receiving node,
indicating that the receiving node will be the one initiating communication.
This process allows Launchpad to define cross-service communication simply
by passing handles to nodes. The open-sourced version of Launchpad currently
provides following types of nodes (you can implement your own types as needed):

*   **PyNode** - a simple node executing provided Python code upon entry.
    It is similar to a main function, but with the distinction that
    each node may be running in separate processes and on different machines.
*   **CourierNode** - it enables cross-node communication. **CourierNodes** can
    communicate by calling public methods on each other either synchronously
    or asynchronously via futures. The underlying remote procedure calls
    are handled transparently by Launchpad.
*   **ReverbNode** - it exposes functionality of Reverb, an easy-to-use data
    storage and transport system primarily used by RL algorithms as
    an experience replay. You can read more about Reverb
    [here](https://github.com/deepmind/reverb).
*   **MultiThreadingColocation** - allows to colocate multiple other nodes in
    a single process.

Using Launchpad involves implementing nodes and defining the topology of your
distributed program by passing to each node references of the other nodes that
it can communicate with. The core data structure dealing with this is called a
**Launchpad program**, which can then be used for local debugging runs, tests,
distributed executions, etc.

## Table of Contents

-   [Installation](#installation)
-   [Quick Start](#quick-start)
    -   [Implement example nodes](#implement-example-nodes)
    -   [Define the topology](#define-the-topology)
    -   [Launch the program](#launch-the-program)
    -   [Add a test](#add-a-test)

## Installation

Please keep in mind that Launchpad is not hardened for production use, and while we
do our best to keep things in working order, things may break or segfault.

> :warning: Launchpad currently only supports Linux based OSes.

The recommended way to install Launchpad is with `pip`. We also provide
instructions to build from source using the same docker images we use for
releases.

TensorFlow can be installed separately or as part of the `pip` install.
Installing TensorFlow as part of the install ensures compatibility.

```shell
$ pip install dm-launchpad[tensorflow]

# Without Tensorflow install and version dependency check.
$ pip install dm-launchpad
```

### Nightly builds

[![PyPI version](https://badge.fury.io/py/dm-launchpad-nightly.svg)](https://badge.fury.io/py/dm-launchpad-nightly)

```shell
$ pip install dm-launchpad-nightly[tensorflow]

# Without Tensorflow install and version dependency check.
$ pip install dm-launchpad-nightly
```

Similarily, [Reverb](https://github.com/deepmind/reverb) can be installed
ensuring compatibility:

```shell
$ pip install dm-launchpad[reverb]
```

### Develop Launchpad inside a docker container

The most convenient way to develop Launchpad is with Docker.
This way you can compile and test Launchpad inside a container without
having to install anything on your host machine, while you can still
use your editor of choice for making code changes.
The steps are as follows.

Checkout Launchpad's source code from GitHub.
```
$ git checkout https://github.com/deepmind/launchpad.git
$ cd launchpad
```

Build the Docker container to be used for compiling and testing Launchpad.
You can specify `tensorflow_pip` parameter to set the version
of Tensorflow to build against. You can also specify which version(s) of Python
container should support. The command below enables support for Python
3.6, 3.7, 3.8 and 3.9.
```
$ docker build --tag launchpad:devel \
  --build-arg tensorflow_pip=tensorflow==2.3.0 \
  --build-arg python_version="3.6 3.7 3.8 3.9" - < docker/build.dockerfile
```

The next step is to enter the built Docker image, binding checked out
Launchpad's sources to /tmp/launchpad within the container.
```
$ docker run --rm --mount "type=bind,src=$PWD,dst=/tmp/launchpad" \
  -it launchpad:devel bash
```

At this point you can build and install Launchpad within the container by
executing:
```
$ /tmp/launchpad/oss_build.sh
```

By default it builds Python 3.8 version, you can change that with `--python`
flag.
```
$ /tmp/launchpad/oss_build.sh --python 3.6
```

To make sure installation was successful and Launchpad works as expected, you
can run some examples provided:
```
$ python3.6 -m launchpad.examples.hello_world.launch
$ python3.6 -m launchpad.examples.consumer_producers.launch --lp_launch_type=local_mp
```

To make changes to Launchpad codebase, edit sources checked out from GitHub
directly on your host machine (outside of the Docker container). All changes are
visible inside the Docker container. To recompile just run the `oss_build.sh`
script again from the Docker container. In order to reduce compilation time of
the consecutive runs, make sure to not exit the Docker container.

## Quick Start

The complete implementation can be found
[here](https://github.com/deepmind/launchpad/tree/master/launchpad/examples/consumer_producers/).

## Implement example nodes

In this producer-consumer example, we have one consumer and multiple producers.
The consumer sends work to the producers, which perform some time-intensive
task before returning the result to the consumer. Finally, the consumer
summarizes the work done by all of the producers.

![consumer-producer-topology](docs/images/consumer_producers.png)

The producer in this example has just one method which performs some work (for
you to implement) in a given context provided by the caller. Any method of the
class can be exposed for other nodes to call by wrapping a node with a
**CourierNode**. In a typical setup, all nodes live in separate processes or on
distinct machines, while the communication between the nodes is taken care of
transparently by Launchpad. Some care has to be taken though. For
example, the `work()` method may be called from multiple threads within the same
process, so if the producer were to have any shared state then access to it must
be made thread-safe. In this case, the producer is stateless so it is not a
concern.

```python
class Producer:
  def work(self, context):
    return context
```

The consumer defines an initializer and a `run()` method. The initializer takes
a list of handles to the producers (**CourierNode**s).

Any Launchpad **PyClassNode** with a `run()` method will have that method called
automatically upon program entry. Here the `run()` method simply calls `work()`
on each producer and collects the results. At the end, it calls
`launchpad.stop()` to terminate all nodes running within a program.

```python
class Consumer:
  def __init__(self, producers):
    self._producers = producers

  def run(self):
    results = [producer.work(context)
               for context, producer in enumerate(self._producers)]
    logging.info('Results: %s', results)
    lp.stop()
```

In the example above, `work()` methods are called sequentially, so there is no
benefit in running this program distributed. Launchpad, however, allows for
asynchronous calls as well through the use of futures. In the example below
all producers will perform their work in parallel while consumer waits
on all of their results when calling `future.result()`.

```python
class Consumer:
  def __init__(self, producers):
    self._producers = producers

  def run(self):
    futures = [producer.futures.work(context)
               for context, producer in enumerate(self._producers)]
    results = [future.result() for future in futures]
    logging.info('Results: %s', results)
    launchpad.stop()
```

## Define the topology

The next step is to instantiate nodes for the consumer and producers and then
connect them so that the consumer can call methods on the producers. The
connections between nodes define the topology of the distributed program.

Launchpad uses an `lp.Program` class to hold all the nodes. There are several
different types of nodes but here `lp.CourierNode` is used since it is the
simplest type which supports communication between nodes. The parameters to
`lp.CourierNode` are the name of the class and the parameters of its
initializer. Connecting the consumer node to the producer nodes is as simple as
passing in handles to all producers in the initializer of the consumer.
The handles themselves are returned by `lp.Program.add_node()`.


```python
def make_program(num_producers):
  program = lp.Program('consumer_producers')
  with program.group('producer'):
    producers = [
        program.add_node(lp.CourierNode(Producer)) for _ in range(num_producers)
    ]
  node = lp.CourierNode(
      Consumer,
      producers=producers)
  program.add_node(node, label='consumer')
  return program
```

With the above function defining the topology all that remains is to implement
`main()` for Launchpad:

```python
def main(_):
  program = make_program(num_producers=FLAGS.num_producers)
  lp.launch(program)

if __name__ == '__main__':
  app.run(main)
```

## Launch the program

To launch the program (assuming it is called `launch.py`), simply run:

```sh
python3 -m launch --lp_launch_type=local_mp
```

The `--lp_launch_type` controls how the program is launched. In the above case
it is launched locally with each node executed in a separate process.
List of supported execution modes can be found
[here](https://github.com/deepmind/launchpad/tree/master/launchpad/context.py).

## Add a test

Here are some points to keep in mind when creating a test for a Launchpad
program.

*   The easiest way to add a test for your program is to reuse the same topology
    for an integration test (i.e. call `make_program()` from above in
    this example).
*   Launch a test by calling `lp.launch()` just like in `main()` in the above
    example, but explicitly specify `launch_type='test_mt'` (multithreaded
    tests) as a parameter.
*   It is possible to disable automatic execution of a node's `run()` method
    before launching. Do so by calling `disable_run()` on the node in question.
*   In order to call methods to test on a Courier node you will need to
    explicitly dereference the handle of the node first. Do so by calling
    `create_handle()` followed by `dereference()` on the node in question.

Below is an incomplete example illustrating the above concepts. A complete
example can be found [here](https://github.com/deepmind/launchpad/tree/master/launchpad/examples/consumer_producers/launch_test.py).

```python
import launchpad as lp
from launchpad.examples.consumer_producers import launch
from absl.testing import absltest

class LaunchTest(absltest.TestCase):
  def test_consumer(self):
    program = launch.make_program(num_producers=2)
    (consumer_node,) = program.groups['consumer']
    consumer_node.disable_run()
    lp.launch(program, launch_type='test_mt')
    consumer = consumer_node.create_handle().dereference()
    # Perform actual test here by calling methods on `consumer` ...
```

## Citing Launchpad

If you use Launchpad in your work, please cite the accompanying
[technical report](https://arxiv.org/pdf/2106.04516):

```bibtex
@article{yang2021launchpad,
    title={Launchpad: A Programming Model for Distributed Machine Learning
           Research},
    author={Fan Yang and Gabriel Barth-Maron and Piotr Stańczyk and Matthew
            Hoffman and Siqi Liu and Manuel Kroiss and Aedan Pope and Alban
            Rrustemi},
    year={2021},
    journal={arXiv preprint arXiv:2106.04516},
    url={https://arxiv.org/abs/2106.04516},
}
```

## Acknowledgements

We greatly appreciate all the help from [Reverb](https://github.com/deepmind/reverb)
and [TF-Agents](https://github.com/tensorflow/agents) teams in setting
up building and testing setup for Launchpad.



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/deepmind/launchpad",
    "name": "dm-launchpad-nightly",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3",
    "maintainer_email": "",
    "keywords": "deepmind reinforcement learning machine distributed",
    "author": "DeepMind",
    "author_email": "DeepMind <no-reply@google.com>",
    "download_url": "",
    "platform": "",
    "description": "# Launchpad\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dm-launchpad)\n[![PyPI version](https://badge.fury.io/py/dm-launchpad.svg)](https://badge.fury.io/py/dm-launchpad)\n\nLaunchpad is a library that simplifies writing distributed programs by\nseamlessly launching them on a variety of different platforms. Switching between\nlocal and distributed execution requires only a flag change.\n\nLaunchpad introduces a programming model that represents a distributed system\nas a graph data structure (a **Program**) describing the system\u2019s topology.\nEach node in the program graph represents a service in the distributed system,\ni.e. the fundamental unit of computation that we are interested in running.\nAs nodes are added to this graph, Launchpad constructs a handle for each of them.\nA handle ultimately represents a client to the yet-to-be-constructed service.\nA directed edge in the program graph, representing communication between\ntwo services, is created when the handle associated with one node is given\nto another at construction time. This edge originates from the receiving node,\nindicating that the receiving node will be the one initiating communication.\nThis process allows Launchpad to define cross-service communication simply\nby passing handles to nodes. The open-sourced version of Launchpad currently\nprovides following types of nodes (you can implement your own types as needed):\n\n*   **PyNode** - a simple node executing provided Python code upon entry.\n    It is similar to a main function, but with the distinction that\n    each node may be running in separate processes and on different machines.\n*   **CourierNode** - it enables cross-node communication. **CourierNodes** can\n    communicate by calling public methods on each other either synchronously\n    or asynchronously via futures. The underlying remote procedure calls\n    are handled transparently by Launchpad.\n*   **ReverbNode** - it exposes functionality of Reverb, an easy-to-use data\n    storage and transport system primarily used by RL algorithms as\n    an experience replay. You can read more about Reverb\n    [here](https://github.com/deepmind/reverb).\n*   **MultiThreadingColocation** - allows to colocate multiple other nodes in\n    a single process.\n\nUsing Launchpad involves implementing nodes and defining the topology of your\ndistributed program by passing to each node references of the other nodes that\nit can communicate with. The core data structure dealing with this is called a\n**Launchpad program**, which can then be used for local debugging runs, tests,\ndistributed executions, etc.\n\n## Table of Contents\n\n-   [Installation](#installation)\n-   [Quick Start](#quick-start)\n    -   [Implement example nodes](#implement-example-nodes)\n    -   [Define the topology](#define-the-topology)\n    -   [Launch the program](#launch-the-program)\n    -   [Add a test](#add-a-test)\n\n## Installation\n\nPlease keep in mind that Launchpad is not hardened for production use, and while we\ndo our best to keep things in working order, things may break or segfault.\n\n> :warning: Launchpad currently only supports Linux based OSes.\n\nThe recommended way to install Launchpad is with `pip`. We also provide\ninstructions to build from source using the same docker images we use for\nreleases.\n\nTensorFlow can be installed separately or as part of the `pip` install.\nInstalling TensorFlow as part of the install ensures compatibility.\n\n```shell\n$ pip install dm-launchpad[tensorflow]\n\n# Without Tensorflow install and version dependency check.\n$ pip install dm-launchpad\n```\n\n### Nightly builds\n\n[![PyPI version](https://badge.fury.io/py/dm-launchpad-nightly.svg)](https://badge.fury.io/py/dm-launchpad-nightly)\n\n```shell\n$ pip install dm-launchpad-nightly[tensorflow]\n\n# Without Tensorflow install and version dependency check.\n$ pip install dm-launchpad-nightly\n```\n\nSimilarily, [Reverb](https://github.com/deepmind/reverb) can be installed\nensuring compatibility:\n\n```shell\n$ pip install dm-launchpad[reverb]\n```\n\n### Develop Launchpad inside a docker container\n\nThe most convenient way to develop Launchpad is with Docker.\nThis way you can compile and test Launchpad inside a container without\nhaving to install anything on your host machine, while you can still\nuse your editor of choice for making code changes.\nThe steps are as follows.\n\nCheckout Launchpad's source code from GitHub.\n```\n$ git checkout https://github.com/deepmind/launchpad.git\n$ cd launchpad\n```\n\nBuild the Docker container to be used for compiling and testing Launchpad.\nYou can specify `tensorflow_pip` parameter to set the version\nof Tensorflow to build against. You can also specify which version(s) of Python\ncontainer should support. The command below enables support for Python\n3.6, 3.7, 3.8 and 3.9.\n```\n$ docker build --tag launchpad:devel \\\n  --build-arg tensorflow_pip=tensorflow==2.3.0 \\\n  --build-arg python_version=\"3.6 3.7 3.8 3.9\" - < docker/build.dockerfile\n```\n\nThe next step is to enter the built Docker image, binding checked out\nLaunchpad's sources to /tmp/launchpad within the container.\n```\n$ docker run --rm --mount \"type=bind,src=$PWD,dst=/tmp/launchpad\" \\\n  -it launchpad:devel bash\n```\n\nAt this point you can build and install Launchpad within the container by\nexecuting:\n```\n$ /tmp/launchpad/oss_build.sh\n```\n\nBy default it builds Python 3.8 version, you can change that with `--python`\nflag.\n```\n$ /tmp/launchpad/oss_build.sh --python 3.6\n```\n\nTo make sure installation was successful and Launchpad works as expected, you\ncan run some examples provided:\n```\n$ python3.6 -m launchpad.examples.hello_world.launch\n$ python3.6 -m launchpad.examples.consumer_producers.launch --lp_launch_type=local_mp\n```\n\nTo make changes to Launchpad codebase, edit sources checked out from GitHub\ndirectly on your host machine (outside of the Docker container). All changes are\nvisible inside the Docker container. To recompile just run the `oss_build.sh`\nscript again from the Docker container. In order to reduce compilation time of\nthe consecutive runs, make sure to not exit the Docker container.\n\n## Quick Start\n\nThe complete implementation can be found\n[here](https://github.com/deepmind/launchpad/tree/master/launchpad/examples/consumer_producers/).\n\n## Implement example nodes\n\nIn this producer-consumer example, we have one consumer and multiple producers.\nThe consumer sends work to the producers, which perform some time-intensive\ntask before returning the result to the consumer. Finally, the consumer\nsummarizes the work done by all of the producers.\n\n![consumer-producer-topology](docs/images/consumer_producers.png)\n\nThe producer in this example has just one method which performs some work (for\nyou to implement) in a given context provided by the caller. Any method of the\nclass can be exposed for other nodes to call by wrapping a node with a\n**CourierNode**. In a typical setup, all nodes live in separate processes or on\ndistinct machines, while the communication between the nodes is taken care of\ntransparently by Launchpad. Some care has to be taken though. For\nexample, the `work()` method may be called from multiple threads within the same\nprocess, so if the producer were to have any shared state then access to it must\nbe made thread-safe. In this case, the producer is stateless so it is not a\nconcern.\n\n```python\nclass Producer:\n  def work(self, context):\n    return context\n```\n\nThe consumer defines an initializer and a `run()` method. The initializer takes\na list of handles to the producers (**CourierNode**s).\n\nAny Launchpad **PyClassNode** with a `run()` method will have that method called\nautomatically upon program entry. Here the `run()` method simply calls `work()`\non each producer and collects the results. At the end, it calls\n`launchpad.stop()` to terminate all nodes running within a program.\n\n```python\nclass Consumer:\n  def __init__(self, producers):\n    self._producers = producers\n\n  def run(self):\n    results = [producer.work(context)\n               for context, producer in enumerate(self._producers)]\n    logging.info('Results: %s', results)\n    lp.stop()\n```\n\nIn the example above, `work()` methods are called sequentially, so there is no\nbenefit in running this program distributed. Launchpad, however, allows for\nasynchronous calls as well through the use of futures. In the example below\nall producers will perform their work in parallel while consumer waits\non all of their results when calling `future.result()`.\n\n```python\nclass Consumer:\n  def __init__(self, producers):\n    self._producers = producers\n\n  def run(self):\n    futures = [producer.futures.work(context)\n               for context, producer in enumerate(self._producers)]\n    results = [future.result() for future in futures]\n    logging.info('Results: %s', results)\n    launchpad.stop()\n```\n\n## Define the topology\n\nThe next step is to instantiate nodes for the consumer and producers and then\nconnect them so that the consumer can call methods on the producers. The\nconnections between nodes define the topology of the distributed program.\n\nLaunchpad uses an `lp.Program` class to hold all the nodes. There are several\ndifferent types of nodes but here `lp.CourierNode` is used since it is the\nsimplest type which supports communication between nodes. The parameters to\n`lp.CourierNode` are the name of the class and the parameters of its\ninitializer. Connecting the consumer node to the producer nodes is as simple as\npassing in handles to all producers in the initializer of the consumer.\nThe handles themselves are returned by `lp.Program.add_node()`.\n\n\n```python\ndef make_program(num_producers):\n  program = lp.Program('consumer_producers')\n  with program.group('producer'):\n    producers = [\n        program.add_node(lp.CourierNode(Producer)) for _ in range(num_producers)\n    ]\n  node = lp.CourierNode(\n      Consumer,\n      producers=producers)\n  program.add_node(node, label='consumer')\n  return program\n```\n\nWith the above function defining the topology all that remains is to implement\n`main()` for Launchpad:\n\n```python\ndef main(_):\n  program = make_program(num_producers=FLAGS.num_producers)\n  lp.launch(program)\n\nif __name__ == '__main__':\n  app.run(main)\n```\n\n## Launch the program\n\nTo launch the program (assuming it is called `launch.py`), simply run:\n\n```sh\npython3 -m launch --lp_launch_type=local_mp\n```\n\nThe `--lp_launch_type` controls how the program is launched. In the above case\nit is launched locally with each node executed in a separate process.\nList of supported execution modes can be found\n[here](https://github.com/deepmind/launchpad/tree/master/launchpad/context.py).\n\n## Add a test\n\nHere are some points to keep in mind when creating a test for a Launchpad\nprogram.\n\n*   The easiest way to add a test for your program is to reuse the same topology\n    for an integration test (i.e. call `make_program()` from above in\n    this example).\n*   Launch a test by calling `lp.launch()` just like in `main()` in the above\n    example, but explicitly specify `launch_type='test_mt'` (multithreaded\n    tests) as a parameter.\n*   It is possible to disable automatic execution of a node's `run()` method\n    before launching. Do so by calling `disable_run()` on the node in question.\n*   In order to call methods to test on a Courier node you will need to\n    explicitly dereference the handle of the node first. Do so by calling\n    `create_handle()` followed by `dereference()` on the node in question.\n\nBelow is an incomplete example illustrating the above concepts. A complete\nexample can be found [here](https://github.com/deepmind/launchpad/tree/master/launchpad/examples/consumer_producers/launch_test.py).\n\n```python\nimport launchpad as lp\nfrom launchpad.examples.consumer_producers import launch\nfrom absl.testing import absltest\n\nclass LaunchTest(absltest.TestCase):\n  def test_consumer(self):\n    program = launch.make_program(num_producers=2)\n    (consumer_node,) = program.groups['consumer']\n    consumer_node.disable_run()\n    lp.launch(program, launch_type='test_mt')\n    consumer = consumer_node.create_handle().dereference()\n    # Perform actual test here by calling methods on `consumer` ...\n```\n\n## Citing Launchpad\n\nIf you use Launchpad in your work, please cite the accompanying\n[technical report](https://arxiv.org/pdf/2106.04516):\n\n```bibtex\n@article{yang2021launchpad,\n    title={Launchpad: A Programming Model for Distributed Machine Learning\n           Research},\n    author={Fan Yang and Gabriel Barth-Maron and Piotr Sta\u0144czyk and Matthew\n            Hoffman and Siqi Liu and Manuel Kroiss and Aedan Pope and Alban\n            Rrustemi},\n    year={2021},\n    journal={arXiv preprint arXiv:2106.04516},\n    url={https://arxiv.org/abs/2106.04516},\n}\n```\n\n## Acknowledgements\n\nWe greatly appreciate all the help from [Reverb](https://github.com/deepmind/reverb)\nand [TF-Agents](https://github.com/tensorflow/agents) teams in setting\nup building and testing setup for Launchpad.\n\n\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "Launchpad is a library that simplifies writing distributed programs and seamlessly launching them on a range of supported platforms.",
    "version": "0.3.0.dev20210617",
    "split_keywords": [
        "deepmind",
        "reinforcement",
        "learning",
        "machine",
        "distributed"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "dccd44ea92a182030f40b77ba680d909",
                "sha256": "279edbf2993cf0e9af61cbf53c25066ed51826035892769e498cb2aad28773aa"
            },
            "downloads": -1,
            "filename": "dm_launchpad_nightly-0.3.0.dev20210617-cp36-cp36m-manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "dccd44ea92a182030f40b77ba680d909",
            "packagetype": "bdist_wheel",
            "python_version": "cp36",
            "requires_python": ">=3",
            "size": 4092867,
            "upload_time": "2021-06-17T10:21:34",
            "upload_time_iso_8601": "2021-06-17T10:21:34.486252Z",
            "url": "https://files.pythonhosted.org/packages/b0/60/10ff4e2eebe5032a032f853d6c1a97129eff31bf81de7c5df0b561ce992e/dm_launchpad_nightly-0.3.0.dev20210617-cp36-cp36m-manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "8b34886a059790ab73b378a0cf9bdeea",
                "sha256": "6f4cfdc70e3ea57fec41bf7740712b166a27500fb1e2ebca47a46eeb08fc0dc3"
            },
            "downloads": -1,
            "filename": "dm_launchpad_nightly-0.3.0.dev20210617-cp37-cp37m-manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "8b34886a059790ab73b378a0cf9bdeea",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3",
            "size": 4093281,
            "upload_time": "2021-06-17T10:21:37",
            "upload_time_iso_8601": "2021-06-17T10:21:37.378550Z",
            "url": "https://files.pythonhosted.org/packages/a3/50/ab1de8b329dae8438b407fa9367eb4bda11e7dc19ed8e43f0ae23da9e41b/dm_launchpad_nightly-0.3.0.dev20210617-cp37-cp37m-manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "bbd2dd1a679dcc5fb0362feb4271a3ce",
                "sha256": "0a7e332a912e15caf8889bd9e9c825ac9533a6fa1d65605258d1284388e12fc5"
            },
            "downloads": -1,
            "filename": "dm_launchpad_nightly-0.3.0.dev20210617-cp38-cp38-manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "bbd2dd1a679dcc5fb0362feb4271a3ce",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3",
            "size": 4101285,
            "upload_time": "2021-06-17T10:21:39",
            "upload_time_iso_8601": "2021-06-17T10:21:39.990785Z",
            "url": "https://files.pythonhosted.org/packages/f8/cf/d2956f7d854bc3c43d9148c927a5c69d991b4022bda332ae637b3cc0555d/dm_launchpad_nightly-0.3.0.dev20210617-cp38-cp38-manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "4763b60bab1fd024dc2b5d02b9267710",
                "sha256": "238333f1982938dcf16b80421c190d7ecca212f9f67d0a821803284ac5dbc255"
            },
            "downloads": -1,
            "filename": "dm_launchpad_nightly-0.3.0.dev20210617-cp39-cp39-manylinux2010_x86_64.whl",
            "has_sig": false,
            "md5_digest": "4763b60bab1fd024dc2b5d02b9267710",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3",
            "size": 4098817,
            "upload_time": "2021-06-17T10:21:42",
            "upload_time_iso_8601": "2021-06-17T10:21:42.088160Z",
            "url": "https://files.pythonhosted.org/packages/2c/27/355a0d6b9583abbbdc576b3981741b208a54fe1046a6778b38f2684b16a7/dm_launchpad_nightly-0.3.0.dev20210617-cp39-cp39-manylinux2010_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2021-06-17 10:21:34",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": null,
    "github_project": "deepmind",
    "error": "Could not fetch GitHub repository",
    "lcname": "dm-launchpad-nightly"
}
        
Elapsed time: 0.33251s