{ "info": { "author": "Dreem", "author_email": "valentin@dreem.com", "bugtrack_url": null, "classifiers": [], "description": "# Bender Client for Python\n\n> :warning: The full **DOCUMENTATION** on bender-python-client can be found [HERE](https://bender-optimizer.readthedocs.io/en/latest/documentation/python.html).\n\n## Setup\n\n 1. Create an account for free at [bender.dreem.com](https://bender.dreem.com)\n 2. Install bender in your Python environment with ``` pip install bender-client ```\n\n## Usage Example\n\n> Let's use the famous MNIST example where we try to recognize handwritten digits in images.\n\nThe code of the algorithm using [PyTorch](https://pytorch.org/) is the following :\n\n> To use this example, do not forget to ``` pip install numpy torch torchvision ``` .\n\n```python\nfrom __future__ import print_function\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torchvision import datasets, transforms\n\nclass Net(nn.Module):\n def __init__(self, dropout=True, activation=\"relu\", kernel_size=5, conv_depth=10, linear_depth=50):\n super(Net, self).__init__()\n self.conv1 = nn.Conv2d(1, conv_depth, kernel_size=kernel_size)\n self.conv2 = nn.Conv2d(conv_depth, 20, kernel_size=kernel_size)\n self.conv2_drop = nn.Dropout2d() if dropout is True else lambda x: x\n self.fc1 = nn.Linear(320, linear_depth)\n self.fc2 = nn.Linear(linear_depth, 10)\n self.activation = getattr(F, activation)\n\n def forward(self, x):\n x = self.activation(F.max_pool2d(self.conv1(x), 2))\n x = self.activation(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n x = x.view(-1, 320)\n x = self.activation(self.fc1(x))\n x = F.dropout(x, training=self.training)\n x = self.fc2(x)\n return F.log_softmax(x, dim=1)\n\n\ndef train(model, device, train_loader, optimizer, epoch):\n model.train()\n for batch_idx, (data, target) in enumerate(train_loader):\n data, target = data.to(device), target.to(device)\n optimizer.zero_grad()\n output = model(data)\n loss = F.nll_loss(output, target)\n loss.backward()\n optimizer.step()\n if batch_idx % 10 == 0:\n print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n epoch, batch_idx * len(data), len(train_loader.dataset),\n 100. * batch_idx / len(train_loader), loss.item()))\n\ndef test(model, device, test_loader):\n model.eval()\n test_loss = 0\n correct = 0\n with torch.no_grad():\n for data, target in test_loader:\n data, target = data.to(device), target.to(device)\n output = model(data)\n test_loss += F.nll_loss(output, target, reduction='sum').item()\n pred = output.max(1, keepdim=True)[1]\n correct += pred.eq(target.view_as(pred)).sum().item()\n test_loss /= len(test_loader.dataset)\n print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n test_loss, correct, len(test_loader.dataset),\n 100. * correct / len(test_loader.dataset)))\n return (correct / len(test_loader.dataset))\n\ndef run(epochs=3, lr=0.01, momentum=0.5, dropout=True, activation=\"relu\", kernel_size=5, conv_depth=10, linear_depth=50):\n torch.manual_seed(1)\n device = torch.device(\"cpu\")\n train_loader = torch.utils.data.DataLoader(\n datasets.MNIST('../data', train=True, download=True,\n transform=transforms.Compose([\n transforms.ToTensor(),\n transforms.Normalize((0.1307,), (0.3081,))\n ])),\n batch_size=32,\n shuffle=True,\n )\n test_loader = torch.utils.data.DataLoader(\n datasets.MNIST('../data', train=False, transform=transforms.Compose([\n transforms.ToTensor(),\n transforms.Normalize((0.1307,), (0.3081,))\n ])),\n batch_size=1000,\n shuffle=True,\n )\n\n model = Net(dropout, activation).to(device)\n optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)\n accuracy = 0\n for epoch in range(1, int(epochs) + 1):\n train(model, device, train_loader, optimizer, epoch)\n accuracy = test(model, device, test_loader)\n return accuracy\n\nif __name__ == '__main__':\n # HYPERPARAMETERS (That's what bender is interested in)\n # Here we select them on our own in an arbitrary way\n hyperparameters = {\n \"kernel_size\": 5,\n \"epochs\": 3,\n \"lr\": 0.05,\n \"momentum\": 0.2,\n \"dropout\": True,\n \"activation\": \"relu\",\n \"conv_depth\": 10,\n \"linear_depth\": 50,\n }\n run(\n epochs=hyperparameters[\"epochs\"],\n lr=hyperparameters[\"lr\"],\n momentum=hyperparameters[\"momentum\"],\n dropout=hyperparameters[\"dropout\"],\n activation=hyperparameters[\"activation\"],\n kernel_size=hyperparameters[\"kernel_size\"],\n conv_depth=hyperparameters[\"conv_depth\"],\n linear_depth=hyperparameters[\"linear_depth\"],\n )\n```\n\n***Now let's plug Bender into It !***\n\n 1. **Importing Bender**\n```python\nfrom benderclient import Bender\nbender = Bender()\n```\n\n> This will ask for your email and password. The client will use these to login and retrieve a TOKEN.\n> This TOKEN is personal, it should not be shared, it will be stored in your home folder as \"`.bender_token`\", and you will not be asked for your login/password again until it expires.\n>:warning: Again, your TOKEN is personal. You should not give it or add it to any public repository :warning:\n\n 2. **Create an Experiment**\n> *An experiment is related to the problem you are trying to solve, here : MNIST classification*\n```python\nbender.new_experiment(\n\tname='MNIST Classification',\n\tdescription='Simple image classification on handwritten digits',\n\tmetrics=[\n\t\t{\n\t\t\t\"metric_name\": \"algorithm_accuracy\", # It's just a name and there can be multiple watched metrics.\n\t\t\t\"type\": \"reward\", # The type can either be \"reward\" or \"loss\" depending on if you want to maximize or minimize it.\n\t\t}\n\t],\n\tdataset='MNIST'\n)\n```\n3. **Create an Algo**\n> *An algo is simply corresponding to ONE solution to an Experiment problem : here it's as we saw a Neural Net with PyTorch*\n```python\nbender.new_algo(\n\tname='PyTorch_NN',\n\t# The parameters below are actually the Hyper-Parameters of your algo described in a list\n\tparameters= [\n {\n \"name\": 'kernel_size',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [3, 5, 7],\n },\n },\n {\n \"name\": 'conv_depth',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 100,\n \"step\": 1,\n },\n },\n {\n \"name\": 'linear_depth',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 100,\n \"step\": 1,\n },\n },\n {\n \"name\": 'epochs',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 4,\n \"step\": 1,\n },\n },\n {\n \"name\": 'lr',\n \"category\": \"loguniform\",\n \"search_space\": {\n \"low\": 1e-5,\n \"high\": 1e-1,\n \"step\": 1e-6,\n },\n },\n {\n \"name\": 'momentum',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 0,\n \"high\": 1,\n \"step\": 0.05,\n },\n },\n {\n \"name\": 'dropout',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [True, False],\n },\n },\n {\n \"name\": 'activation',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [\"relu\", \"softmax\", \"sigmoid\", \"tanh\"],\n },\n },\n ]\n)\n```\n\n4. **Get an Hyperparameters Set suggestion from Bender**\n\n> *The whole goal of what we did up there is to use Bender to get a new set of Hyperparameters to try according to the settings of your Experiment and Algo.*\n\n```python\nsuggestion = bender.suggest()\n\n# suggestion would for example contain something like :\n{\n \"kernel_size\": 5,\n \"epochs\": 3,\n \"lr\": 0.05,\n \"momentum\": 0.2,\n \"dropout\": True,\n \"activation\": \"tanh\",\n \"conv_depth\": 10,\n \"linear_depth\": 50,\n}\n```\n\n5. **Feed a Trial to Bender**\n\n> *A Trial is simply an attempt of you trying a Hyperparameters Set with your algorithm associated with the result metrics obtained. If you want bender to improve over time, feed him every trial you make.*\n\n```python\nbender.new_trial(\n\tparameters={\n \"kernel_size\": 5,\n\t\t\"epochs\": 3,\n\t\t\"lr\": 0.05,\n\t\t\"momentum\": 0.2,\n\t\t\"dropout\": True,\n\t\t\"activation\": \"tanh\",\n \"conv_depth\": 10,\n \"linear_depth\": 50,\n\t},\n\tresults={\n\t\t\"algorithm_accuracy\": 0.7, # We put an arbitrary value here just for the example.\n\t}\n)\n```\n6. **The full code put together**\n\n> *Psssssst... The magic starts at line 443... ;)*\n\n> To use this example, do not forget to ``` pip install numpy torch torchvision bender-client ``` .\n\n```python\nfrom __future__ import print_function\nimport argparse\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torchvision import datasets, transforms\nfrom benderclient import Bender\n\nclass Net(nn.Module):\n def __init__(self, dropout=True, activation=\"relu\", kernel_size=5, conv_depth=10, linear_depth=50):\n super(Net, self).__init__()\n self.conv1 = nn.Conv2d(1, conv_depth, kernel_size=kernel_size)\n self.conv2 = nn.Conv2d(conv_depth, 20, kernel_size=kernel_size)\n self.conv2_drop = nn.Dropout2d() if dropout is True else lambda x: x\n self.fc1 = nn.Linear(320, linear_depth)\n self.fc2 = nn.Linear(linear_depth, 10)\n self.activation = getattr(F, activation)\n\n def forward(self, x):\n x = self.activation(F.max_pool2d(self.conv1(x), 2))\n x = self.activation(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n x = x.view(-1, 320)\n x = self.activation(self.fc1(x))\n x = F.dropout(x, training=self.training)\n x = self.fc2(x)\n return F.log_softmax(x, dim=1)\n\n\ndef train(model, device, train_loader, optimizer, epoch):\n model.train()\n for batch_idx, (data, target) in enumerate(train_loader):\n data, target = data.to(device), target.to(device)\n optimizer.zero_grad()\n output = model(data)\n loss = F.nll_loss(output, target)\n loss.backward()\n optimizer.step()\n if batch_idx % 10 == 0:\n print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n epoch, batch_idx * len(data), len(train_loader.dataset),\n 100. * batch_idx / len(train_loader), loss.item()))\n\ndef test(model, device, test_loader):\n model.eval()\n test_loss = 0\n correct = 0\n with torch.no_grad():\n for data, target in test_loader:\n data, target = data.to(device), target.to(device)\n output = model(data)\n test_loss += F.nll_loss(output, target, reduction='sum').item()\n pred = output.max(1, keepdim=True)[1]\n correct += pred.eq(target.view_as(pred)).sum().item()\n test_loss /= len(test_loader.dataset)\n print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n test_loss, correct, len(test_loader.dataset),\n 100. * correct / len(test_loader.dataset)))\n return (correct / len(test_loader.dataset))\n\ndef run(epochs=3, lr=0.01, momentum=0.5, dropout=True, activation=\"relu\", kernel_size=5, conv_depth=10, linear_depth=50):\n torch.manual_seed(1)\n device = torch.device(\"cpu\")\n train_loader = torch.utils.data.DataLoader(\n datasets.MNIST('../data', train=True, download=True,\n transform=transforms.Compose([\n transforms.ToTensor(),\n transforms.Normalize((0.1307,), (0.3081,))\n ])),\n batch_size=32,\n shuffle=True,\n )\n test_loader = torch.utils.data.DataLoader(\n datasets.MNIST('../data', train=False, transform=transforms.Compose([\n transforms.ToTensor(),\n transforms.Normalize((0.1307,), (0.3081,))\n ])),\n batch_size=1000,\n shuffle=True,\n )\n\n model = Net(dropout, activation).to(device)\n optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)\n accuracy = 0\n for epoch in range(1, int(epochs) + 1):\n train(model, device, train_loader, optimizer, epoch)\n accuracy = test(model, device, test_loader)\n return accuracy\n\ndef init_bender():\n bender = Bender()\n bender.create_experiment(\n name='MNIST Classification',\n description='Simple image classification on handwritten digits',\n metrics=[{\"metric_name\": \"algorithm_accuracy\", \"type\": \"reward\"}],\n dataset='MNIST'\n )\n bender.create_algo(\n name='PyTorch_NN',\n hyperparameters= [\n {\n \"name\": 'kernel_size',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [3, 5, 7],\n },\n },\n {\n \"name\": 'conv_depth',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 100,\n \"step\": 1,\n },\n },\n {\n \"name\": 'linear_depth',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 100,\n \"step\": 1,\n },\n },\n {\n \"name\": 'epochs',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 1,\n \"high\": 4,\n \"step\": 1,\n },\n },\n {\n \"name\": 'lr',\n \"category\": \"loguniform\",\n \"search_space\": {\n \"low\": 1e-5,\n \"high\": 1e-1,\n \"step\": 1e-6,\n },\n },\n {\n \"name\": 'momentum',\n \"category\": \"uniform\",\n \"search_space\": {\n \"low\": 0,\n \"high\": 1,\n \"step\": 0.05,\n },\n },\n {\n \"name\": 'dropout',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [True, False],\n },\n },\n {\n \"name\": 'activation',\n \"category\": \"categorical\",\n \"search_space\": {\n \"values\": [\"relu\", \"softmax\", \"sigmoid\", \"tanh\"],\n },\n },\n ]\n )\n return bender\n\nif __name__ == '__main__':\n # Create experiment and algo if they don't exist yet. Else, load them from the config file ./.benderconf\n bender = init_bender()\n while True:\n # Get a set of Hyperparameters to test\n suggestion = bender.suggest(metric=\"algorithm_accuracy\")\n # Get algo result with them\n result = run(\n epochs=suggestion[\"epochs\"],\n lr=suggestion[\"lr\"],\n momentum=suggestion[\"momentum\"],\n dropout=suggestion[\"dropout\"],\n activation=suggestion[\"activation\"],\n kernel_size=suggestion[\"kernel_size\"],\n conv_depth=suggestion[\"conv_depth\"],\n linear_depth=suggestion[\"linear_depth\"],\n )\n # Feed Bender a Trial, AKA => suggestion + result\n bender.create_trial(\n hyperparameters=suggestion,\n results={\"algorithm_accuracy\": result}\n )\n print('New trial sent -----------------------------------------------------\\n\\n')\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://bender.dreem.com", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "bender-client", "package_url": "https://pypi.org/project/bender-client/", "platform": "", "project_url": "https://pypi.org/project/bender-client/", "project_urls": { "Homepage": "https://bender.dreem.com" }, "release_url": "https://pypi.org/project/bender-client/0.4.0/", "requires_dist": [ "requests (==2.20.1)", "python-jose (==3.0.1)" ], "requires_python": "", "summary": "Bender Python Client", "version": "0.4.0" }, "last_serial": 4816268, "releases": { "0.3.0": [ { "comment_text": "", "digests": { "md5": "4debd8717fffe093437534bf3e392139", "sha256": "052b65a81c3e1651a84e8760888b6fe76f2c1b75a62927a37c4ba50066a9d596" }, "downloads": -1, "filename": "bender_client-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4debd8717fffe093437534bf3e392139", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10023, "upload_time": "2018-11-21T15:34:20", "url": "https://files.pythonhosted.org/packages/bf/82/485f21f23912be9db8bec98514f0ccf32ca820a8c2089bdf3887c7017230/bender_client-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6cc1c6efb8d75d573c1720161d9694c4", "sha256": "f9ece3014df7ba73d335e0f628ce798aefe5f3fa3b1febe64c7266012a6345c0" }, "downloads": -1, "filename": "bender-client-0.3.0.tar.gz", "has_sig": false, "md5_digest": "6cc1c6efb8d75d573c1720161d9694c4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12343, "upload_time": "2018-11-21T15:34:22", "url": "https://files.pythonhosted.org/packages/38/cf/aef8e50af38c47754ff5aa6b8b5e42ab47cc18f2aed5296bc21bcb6f2da8/bender-client-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "5ef2a89622d6873a8081682e99179213", "sha256": "3d2ed4ce7c42031b4690ebc25460d73b5be6bb90a162abbf11a6590d7d093ca5" }, "downloads": -1, "filename": "bender_client-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5ef2a89622d6873a8081682e99179213", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9426, "upload_time": "2018-11-26T20:01:51", "url": "https://files.pythonhosted.org/packages/90/a3/dda6d640f3179ac70d48683c8753c8b7db8581f37137e72f70c683af92f8/bender_client-0.3.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "87a78fe5e103068829e7c76cd7846663", "sha256": "b92b931a80c7b2f34b59f9a3183da2339d7bbdec0dad159f2b3b8c584e1ff49a" }, "downloads": -1, "filename": "bender-client-0.3.1.tar.gz", "has_sig": false, "md5_digest": "87a78fe5e103068829e7c76cd7846663", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9875, "upload_time": "2018-11-26T20:01:53", "url": "https://files.pythonhosted.org/packages/8a/14/22a4c591edf40466d1906b86c3d1b396a1624443d9210407d84e5cdafe48/bender-client-0.3.1.tar.gz" } ], "0.3.1.1": [ { "comment_text": "", "digests": { "md5": "f6f00878243c2764d360b0eb57fbdb1c", "sha256": "260b921a4f2bc930628a8d4ed18b1a7548193846f49bdcea202c2bec29155027" }, "downloads": -1, "filename": "bender_client-0.3.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "f6f00878243c2764d360b0eb57fbdb1c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9452, "upload_time": "2018-11-27T15:44:05", "url": "https://files.pythonhosted.org/packages/86/4b/770bc5e242588820f0c03b6eee8ee4541e23eb3fff241ec2fdd6226b1636/bender_client-0.3.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6ed205798129ed1b995946bb9227041c", "sha256": "6efaf99f5d7771e64fce75b0820f591041f48cee3aa93cef21cb879252d46b48" }, "downloads": -1, "filename": "bender-client-0.3.1.1.tar.gz", "has_sig": false, "md5_digest": "6ed205798129ed1b995946bb9227041c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9894, "upload_time": "2018-11-27T15:44:06", "url": "https://files.pythonhosted.org/packages/fb/7c/bf68aa7f900f363c2348ea3856abfa11cbfa130cf18c0e0bee4f6d052e1e/bender-client-0.3.1.1.tar.gz" } ], "0.3.1.3": [ { "comment_text": "", "digests": { "md5": "df9b216794b2ee7ffe1cbc049b658d8a", "sha256": "9d965a15cf470c97c5defc71570dab580578493bed40b21ea27849112a3218a0" }, "downloads": -1, "filename": "bender_client-0.3.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "df9b216794b2ee7ffe1cbc049b658d8a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9451, "upload_time": "2018-12-17T14:38:20", "url": "https://files.pythonhosted.org/packages/00/46/20f9e36b18b46b8fcc2b969aeeb30cdbc7f93d2f2c7b69d2b773418754d8/bender_client-0.3.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ab5839db5a888d5a5d411816edfb1857", "sha256": "c45543cf67ddcdb8d2f27d73ed3d9aee04400e068648db9961998d9f400d4bd1" }, "downloads": -1, "filename": "bender-client-0.3.1.3.tar.gz", "has_sig": false, "md5_digest": "ab5839db5a888d5a5d411816edfb1857", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9807, "upload_time": "2018-12-17T14:38:21", "url": "https://files.pythonhosted.org/packages/f0/71/aa191802f5ed1ed71c3724a36094b7e3a03589e50bcc7b18ae829d35e3f3/bender-client-0.3.1.3.tar.gz" } ], "0.3.1.5": [ { "comment_text": "", "digests": { "md5": "7bd9386a7bf81fd0cb1ee1633e0c10d0", "sha256": "c20c916b7d623f449fee1106e8060d6d72ba8aeda2b2022d48a32ccef98755c5" }, "downloads": -1, "filename": "bender_client-0.3.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "7bd9386a7bf81fd0cb1ee1633e0c10d0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13443, "upload_time": "2018-12-20T15:51:25", "url": "https://files.pythonhosted.org/packages/ff/0e/1a820611fa18f0039f1d93323ab0c1101966abc985962e18166772087daa/bender_client-0.3.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ef3da46b93e3ee88e6cab56a2e3a229b", "sha256": "492fd8ce8196b028555101dd1cc523b58dbd524ab9faa318e6cdf180f4cbe301" }, "downloads": -1, "filename": "bender-client-0.3.1.5.tar.gz", "has_sig": false, "md5_digest": "ef3da46b93e3ee88e6cab56a2e3a229b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9250, "upload_time": "2018-12-20T15:51:28", "url": "https://files.pythonhosted.org/packages/b1/e6/1b26f56f72c17496a3fb78a0ba01a2fe1e6c9d1431c66dd889dd12be40df/bender-client-0.3.1.5.tar.gz" } ], "0.3.2.0": [ { "comment_text": "", "digests": { "md5": "e972716750ad68aa51a0a15bd9fbdb33", "sha256": "a52b2fa79bce3ccf7d702ef89e510735d655d525447572e0e921a237702f6d72" }, "downloads": -1, "filename": "bender_client-0.3.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e972716750ad68aa51a0a15bd9fbdb33", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13442, "upload_time": "2018-12-20T15:51:27", "url": "https://files.pythonhosted.org/packages/42/4c/137d1c54025efa23f6a39066c97feb371a6192516c96bafecf73a45c8160/bender_client-0.3.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cf854471f523c2837beed826e4354c42", "sha256": "97f9a104fe7ebe2c7eaf0d022c743a94ec32be9a49311677d76cc26802e14fcf" }, "downloads": -1, "filename": "bender-client-0.3.2.0.tar.gz", "has_sig": false, "md5_digest": "cf854471f523c2837beed826e4354c42", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9245, "upload_time": "2018-12-20T15:51:29", "url": "https://files.pythonhosted.org/packages/d4/15/f35af37b8f3ece90fa5cb6f643d6a32a4bc901e5cfc6789a2d6c646cbc5f/bender-client-0.3.2.0.tar.gz" } ], "0.3.2.1": [ { "comment_text": "", "digests": { "md5": "5e43fc8dac05fe8cd2b7ea8220bd5a07", "sha256": "d761c7848cc9e300e088824753cf8303adbd22ff3a050a51a55f5f6faf73d58c" }, "downloads": -1, "filename": "bender_client-0.3.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5e43fc8dac05fe8cd2b7ea8220bd5a07", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9496, "upload_time": "2019-01-04T16:39:57", "url": "https://files.pythonhosted.org/packages/55/71/241952c5c6916366876bb27f453d2e0c23adca325c0a1e9d03efe0a1b779/bender_client-0.3.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b8bc3bee59e17159d28a033c455aa1d1", "sha256": "a3801bae793bf2b18e671dbc7f4a62ddaa0f794938cd60c8899ec37609291e80" }, "downloads": -1, "filename": "bender-client-0.3.2.1.tar.gz", "has_sig": false, "md5_digest": "b8bc3bee59e17159d28a033c455aa1d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9251, "upload_time": "2019-01-04T16:39:58", "url": "https://files.pythonhosted.org/packages/cf/04/c5bbf8ea9a7928099c354e726445fedafcd88140618cbb995526e2b00412/bender-client-0.3.2.1.tar.gz" } ], "0.3.2.2": [ { "comment_text": "", "digests": { "md5": "3a54bbb6f55f4f38aa3b7cb2512f09ec", "sha256": "513c6555651f373aa55e66a8baf1ec077f749493ad37773ce075fa1f06618362" }, "downloads": -1, "filename": "bender_client-0.3.2.2-py3-none-any.whl", "has_sig": false, "md5_digest": "3a54bbb6f55f4f38aa3b7cb2512f09ec", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9455, "upload_time": "2019-02-11T17:10:21", "url": "https://files.pythonhosted.org/packages/18/d2/9fe42e487f43edcd89bc6a5043e8a0088f83acd921e90a1f1b4cacba852c/bender_client-0.3.2.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "131afb1b8294c53a4a749de4fdb6ebd4", "sha256": "cfa7894e66065e006bfd0e8ce3be0886ad03776b3f7d6acb2cafd79857d7a415" }, "downloads": -1, "filename": "bender-client-0.3.2.2.tar.gz", "has_sig": false, "md5_digest": "131afb1b8294c53a4a749de4fdb6ebd4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9193, "upload_time": "2019-02-11T17:10:23", "url": "https://files.pythonhosted.org/packages/64/e3/81851cc981bf57f08db90a0cfdda90310b80acbaf432e0d34368abd02fa9/bender-client-0.3.2.2.tar.gz" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "0a6aafd6746619b72f1c088c4608401b", "sha256": "8d933eaf3d9ac79b1e24b7515cbc4bb61faae3db066c7ba83305ad8e1bfc027b" }, "downloads": -1, "filename": "bender_client-0.3.3-py3-none-any.whl", "has_sig": false, "md5_digest": "0a6aafd6746619b72f1c088c4608401b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9433, "upload_time": "2019-02-11T17:10:44", "url": "https://files.pythonhosted.org/packages/a2/dc/e36526825c836b1ebf32937813029c65e905bf511cd750c56626fb2bcc6d/bender_client-0.3.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bd65aa1bdfae1eb2e255e187ae1519d4", "sha256": "b0181c4596f39b77a397ffcefed4be5f5148b8ff7a8da3eaf05af443f4f75fbe" }, "downloads": -1, "filename": "bender-client-0.3.3.tar.gz", "has_sig": false, "md5_digest": "bd65aa1bdfae1eb2e255e187ae1519d4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9196, "upload_time": "2019-02-11T17:10:45", "url": "https://files.pythonhosted.org/packages/58/37/6b6b872041d6b37991e32883bcbea83d5d37a4cf14681ce0440c92d76c56/bender-client-0.3.3.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "0e8ea7d9100fb0149042061356a96da5", "sha256": "805fe16fb27174badd259f948d39a4694ee1d0ec9fef33207c810509b2652403" }, "downloads": -1, "filename": "bender_client-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0e8ea7d9100fb0149042061356a96da5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9485, "upload_time": "2019-02-13T15:40:22", "url": "https://files.pythonhosted.org/packages/ee/21/05bedb6d47b5323f571f6a2bdb1d1271f46da408fba0a4eb4a833a74847a/bender_client-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a650b6764cc4f490c49ef730c0ef3ff2", "sha256": "f9fc7d4452565ad4e5e266bb148a8179460ed753a5c916eabd5dfeadf7bb9b0f" }, "downloads": -1, "filename": "bender-client-0.4.0.tar.gz", "has_sig": false, "md5_digest": "a650b6764cc4f490c49ef730c0ef3ff2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9252, "upload_time": "2019-02-13T15:40:24", "url": "https://files.pythonhosted.org/packages/35/63/91fbda2084d611276caf78fc9cb9d4f51ddf8d91a0c91ccafb41b7764326/bender-client-0.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0e8ea7d9100fb0149042061356a96da5", "sha256": "805fe16fb27174badd259f948d39a4694ee1d0ec9fef33207c810509b2652403" }, "downloads": -1, "filename": "bender_client-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0e8ea7d9100fb0149042061356a96da5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9485, "upload_time": "2019-02-13T15:40:22", "url": "https://files.pythonhosted.org/packages/ee/21/05bedb6d47b5323f571f6a2bdb1d1271f46da408fba0a4eb4a833a74847a/bender_client-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a650b6764cc4f490c49ef730c0ef3ff2", "sha256": "f9fc7d4452565ad4e5e266bb148a8179460ed753a5c916eabd5dfeadf7bb9b0f" }, "downloads": -1, "filename": "bender-client-0.4.0.tar.gz", "has_sig": false, "md5_digest": "a650b6764cc4f490c49ef730c0ef3ff2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9252, "upload_time": "2019-02-13T15:40:24", "url": "https://files.pythonhosted.org/packages/35/63/91fbda2084d611276caf78fc9cb9d4f51ddf8d91a0c91ccafb41b7764326/bender-client-0.4.0.tar.gz" } ] }