From 65fc369a236b7266ce1942605c2a0c12758c1268 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Wed, 6 Mar 2019 12:02:37 -0800 Subject: [PATCH] 0.3.1 --- Test Notebook.ipynb | 78 +- build/lib/gradio/__init__.py | 2 +- build/lib/gradio/imagenet_class_labels.py | 1000 +++++++++++++++++ build/lib/gradio/inputs.py | 95 +- build/lib/gradio/interface.py | 224 ++-- build/lib/gradio/networking.py | 159 ++- build/lib/gradio/outputs.py | 72 +- build/lib/gradio/templates/base_template.html | 28 + .../gradio/templates/image_upload_input.html | 38 +- build/lib/gradio/templates/label_output.html | 7 + ...-any.whl => gradio-0.3.1-py3-none-any.whl} | Bin 727286 -> 743872 bytes dist/gradio-0.3.1.tar.gz | Bin 0 -> 35138 bytes gradio.egg-info/PKG-INFO | 2 +- gradio.egg-info/SOURCES.txt | 53 +- gradio/outputs.py | 1 - gradio/static/js/class-output.js | 26 +- gradio/static/js/image-upload-input.js | 18 +- setup.py | 2 +- 18 files changed, 1447 insertions(+), 358 deletions(-) create mode 100644 build/lib/gradio/imagenet_class_labels.py create mode 100644 build/lib/gradio/templates/base_template.html create mode 100644 build/lib/gradio/templates/label_output.html rename dist/{gradio-0.2.1-py3-none-any.whl => gradio-0.3.1-py3-none-any.whl} (95%) create mode 100644 dist/gradio-0.3.1.tar.gz diff --git a/Test Notebook.ipynb b/Test Notebook.ipynb index dc27277049..9f70607095 100644 --- a/Test Notebook.ipynb +++ b/Test Notebook.ipynb @@ -29,15 +29,8 @@ "outputs": [], "source": [ "inp = gradio.inputs.ImageUpload(image_width=299, image_height=299)\n", - "out = gradio.outputs.Label(label_names='imagenet1000', max_label_length=8)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ + "out = gradio.outputs.Label(label_names='imagenet1000', max_label_length=8, num_top_classes=5)\n", + "\n", "iface = gradio.Interface(inputs=inp, \n", " outputs=out,\n", " model=model, \n", @@ -54,8 +47,8 @@ "output_type": "stream", "text": [ "NOTE: Gradio is in beta stage, please report all bugs to: a12d@stanford.edu\n", - "Model is running locally at: http://localhost:7860/interface.html\n", - "Model available publicly for 8 hours at: https://efb97fa5.ngrok.io/interface.html\n" + "Model is running locally at: http://localhost:7861/interface.html\n", + "Model available publicly for 8 hours at: http://4d315e61.ngrok.io/interface.html\n" ] }, { @@ -65,50 +58,63 @@ " \n", " " ], "text/plain": [ - "" + "" ] }, "metadata": {}, "output_type": "display_data" }, - { - "data": { - "text/plain": [ - "('http://localhost:7860/interface.html', 'https://efb97fa5.ngrok.io')" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - }, { "name": "stderr", "output_type": "stream", "text": [ - "127.0.0.1 - - [06/Mar/2019 11:24:00] \"GET /interface.html HTTP/1.1\" 200 -\n", - "127.0.0.1 - - [06/Mar/2019 11:24:00] \"GET /interface.html HTTP/1.1\" 200 -\n", - "127.0.0.1 - - [06/Mar/2019 11:24:00] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", - "127.0.0.1 - - [06/Mar/2019 11:24:00] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "dddddddddddddddddddd cleaver,\n", - "dddddddddddddddddddd cleaver,\n" + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:01] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:02] code 404, message File not found\n", + "127.0.0.1 - - [06/Mar/2019 11:55:02] \"GET /favicon.ico HTTP/1.1\" 404 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:08] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/css/style.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/js/utils.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/img/logo_inline.png HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:09] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:55:10] code 404, message File not found\n", + "127.0.0.1 - - [06/Mar/2019 11:55:10] \"GET /favicon.ico HTTP/1.1\" 404 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:07] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:07] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:07] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:07] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:07] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:31] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:43] \"GET /interface.html HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/js/utils.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/css/gradio.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/js/all-io.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/css/style.css HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/js/image-upload-input.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/js/class-output.js HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:44] \"GET /static/img/logo_inline.png HTTP/1.1\" 200 -\n", + "127.0.0.1 - - [06/Mar/2019 11:58:45] code 404, message File not found\n", + "127.0.0.1 - - [06/Mar/2019 11:58:45] \"GET /favicon.ico HTTP/1.1\" 404 -\n" ] } ], "source": [ - "iface.launch(inline=True, browser=True, share=True)" + "iface.launch(inline=True, browser=True, share=True);" ] } ], diff --git a/build/lib/gradio/__init__.py b/build/lib/gradio/__init__.py index ee12ab164f..4b898437e3 100644 --- a/build/lib/gradio/__init__.py +++ b/build/lib/gradio/__init__.py @@ -1 +1 @@ -from gradio.interface import Interface # This makes Interface importable as gradio.Interface. +from gradio.interface import Interface # This makes it possible to import `Interface` as `gradio.Interface`. diff --git a/build/lib/gradio/imagenet_class_labels.py b/build/lib/gradio/imagenet_class_labels.py new file mode 100644 index 0000000000..b8ed7a7682 --- /dev/null +++ b/build/lib/gradio/imagenet_class_labels.py @@ -0,0 +1,1000 @@ +NAMES1000 = {0: 'tench, Tinca tinca', + 1: 'goldfish, Carassius auratus', + 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', + 3: 'tiger shark, Galeocerdo cuvieri', + 4: 'hammerhead, hammerhead shark', + 5: 'electric ray, crampfish, numbfish, torpedo', + 6: 'stingray', + 7: 'cock', + 8: 'hen', + 9: 'ostrich, Struthio camelus', + 10: 'brambling, Fringilla montifringilla', + 11: 'goldfinch, Carduelis carduelis', + 12: 'house finch, linnet, Carpodacus mexicanus', + 13: 'junco, snowbird', + 14: 'indigo bunting, indigo finch, indigo bird, Passerina cyanea', + 15: 'robin, American robin, Turdus migratorius', + 16: 'bulbul', + 17: 'jay', + 18: 'magpie', + 19: 'chickadee', + 20: 'water ouzel, dipper', + 21: 'kite', + 22: 'bald eagle, American eagle, Haliaeetus leucocephalus', + 23: 'vulture', + 24: 'great grey owl, great gray owl, Strix nebulosa', + 25: 'European fire salamander, Salamandra salamandra', + 26: 'common newt, Triturus vulgaris', + 27: 'eft', + 28: 'spotted salamander, Ambystoma maculatum', + 29: 'axolotl, mud puppy, Ambystoma mexicanum', + 30: 'bullfrog, Rana catesbeiana', + 31: 'tree frog, tree-frog', + 32: 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui', + 33: 'loggerhead, loggerhead turtle, Caretta caretta', + 34: 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea', + 35: 'mud turtle', + 36: 'terrapin', + 37: 'box turtle, box tortoise', + 38: 'banded gecko', + 39: 'common iguana, iguana, Iguana iguana', + 40: 'American chameleon, anole, Anolis carolinensis', + 41: 'whiptail, whiptail lizard', + 42: 'agama', + 43: 'frilled lizard, Chlamydosaurus kingi', + 44: 'alligator lizard', + 45: 'Gila monster, Heloderma suspectum', + 46: 'green lizard, Lacerta viridis', + 47: 'African chameleon, Chamaeleo chamaeleon', + 48: 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis', + 49: 'African crocodile, Nile crocodile, Crocodylus niloticus', + 50: 'American alligator, Alligator mississipiensis', + 51: 'triceratops', + 52: 'thunder snake, worm snake, Carphophis amoenus', + 53: 'ringneck snake, ring-necked snake, ring snake', + 54: 'hognose snake, puff adder, sand viper', + 55: 'green snake, grass snake', + 56: 'king snake, kingsnake', + 57: 'garter snake, grass snake', + 58: 'water snake', + 59: 'vine snake', + 60: 'night snake, Hypsiglena torquata', + 61: 'boa constrictor, Constrictor constrictor', + 62: 'rock python, rock snake, Python sebae', + 63: 'Indian cobra, Naja naja', + 64: 'green mamba', + 65: 'sea snake', + 66: 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus', + 67: 'diamondback, diamondback rattlesnake, Crotalus adamanteus', + 68: 'sidewinder, horned rattlesnake, Crotalus cerastes', + 69: 'trilobite', + 70: 'harvestman, daddy longlegs, Phalangium opilio', + 71: 'scorpion', + 72: 'black and gold garden spider, Argiope aurantia', + 73: 'barn spider, Araneus cavaticus', + 74: 'garden spider, Aranea diademata', + 75: 'black widow, Latrodectus mactans', + 76: 'tarantula', + 77: 'wolf spider, hunting spider', + 78: 'tick', + 79: 'centipede', + 80: 'black grouse', + 81: 'ptarmigan', + 82: 'ruffed grouse, partridge, Bonasa umbellus', + 83: 'prairie chicken, prairie grouse, prairie fowl', + 84: 'peacock', + 85: 'quail', + 86: 'partridge', + 87: 'African grey, African gray, Psittacus erithacus', + 88: 'macaw', + 89: 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita', + 90: 'lorikeet', + 91: 'coucal', + 92: 'bee eater', + 93: 'hornbill', + 94: 'hummingbird', + 95: 'jacamar', + 96: 'toucan', + 97: 'drake', + 98: 'red-breasted merganser, Mergus serrator', + 99: 'goose', + 100: 'black swan, Cygnus atratus', + 101: 'tusker', + 102: 'echidna, spiny anteater, anteater', + 103: 'platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus', + 104: 'wallaby, brush kangaroo', + 105: 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus', + 106: 'wombat', + 107: 'jellyfish', + 108: 'sea anemone, anemone', + 109: 'brain coral', + 110: 'flatworm, platyhelminth', + 111: 'nematode, nematode worm, roundworm', + 112: 'conch', + 113: 'snail', + 114: 'slug', + 115: 'sea slug, nudibranch', + 116: 'chiton, coat-of-mail shell, sea cradle, polyplacophore', + 117: 'chambered nautilus, pearly nautilus, nautilus', + 118: 'Dungeness crab, Cancer magister', + 119: 'rock crab, Cancer irroratus', + 120: 'fiddler crab', + 121: 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica', + 122: 'American lobster, Northern lobster, Maine lobster, Homarus americanus', + 123: 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish', + 124: 'crayfish, crawfish, crawdad, crawdaddy', + 125: 'hermit crab', + 126: 'isopod', + 127: 'white stork, Ciconia ciconia', + 128: 'black stork, Ciconia nigra', + 129: 'spoonbill', + 130: 'flamingo', + 131: 'little blue heron, Egretta caerulea', + 132: 'American egret, great white heron, Egretta albus', + 133: 'bittern', + 134: 'crane', + 135: 'limpkin, Aramus pictus', + 136: 'European gallinule, Porphyrio porphyrio', + 137: 'American coot, marsh hen, mud hen, water hen, Fulica americana', + 138: 'bustard', + 139: 'ruddy turnstone, Arenaria interpres', + 140: 'red-backed sandpiper, dunlin, Erolia alpina', + 141: 'redshank, Tringa totanus', + 142: 'dowitcher', + 143: 'oystercatcher, oyster catcher', + 144: 'pelican', + 145: 'king penguin, Aptenodytes patagonica', + 146: 'albatross, mollymawk', + 147: 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus', + 148: 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca', + 149: 'dugong, Dugong dugon', + 150: 'sea lion', + 151: 'Chihuahua', + 152: 'Japanese spaniel', + 153: 'Maltese dog, Maltese terrier, Maltese', + 154: 'Pekinese, Pekingese, Peke', + 155: 'Shih-Tzu', + 156: 'Blenheim spaniel', + 157: 'papillon', + 158: 'toy terrier', + 159: 'Rhodesian ridgeback', + 160: 'Afghan hound, Afghan', + 161: 'basset, basset hound', + 162: 'beagle', + 163: 'bloodhound, sleuthhound', + 164: 'bluetick', + 165: 'black-and-tan coonhound', + 166: 'Walker hound, Walker foxhound', + 167: 'English foxhound', + 168: 'redbone', + 169: 'borzoi, Russian wolfhound', + 170: 'Irish wolfhound', + 171: 'Italian greyhound', + 172: 'whippet', + 173: 'Ibizan hound, Ibizan Podenco', + 174: 'Norwegian elkhound, elkhound', + 175: 'otterhound, otter hound', + 176: 'Saluki, gazelle hound', + 177: 'Scottish deerhound, deerhound', + 178: 'Weimaraner', + 179: 'Staffordshire bullterrier, Staffordshire bull terrier', + 180: 'American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier', + 181: 'Bedlington terrier', + 182: 'Border terrier', + 183: 'Kerry blue terrier', + 184: 'Irish terrier', + 185: 'Norfolk terrier', + 186: 'Norwich terrier', + 187: 'Yorkshire terrier', + 188: 'wire-haired fox terrier', + 189: 'Lakeland terrier', + 190: 'Sealyham terrier, Sealyham', + 191: 'Airedale, Airedale terrier', + 192: 'cairn, cairn terrier', + 193: 'Australian terrier', + 194: 'Dandie Dinmont, Dandie Dinmont terrier', + 195: 'Boston bull, Boston terrier', + 196: 'miniature schnauzer', + 197: 'giant schnauzer', + 198: 'standard schnauzer', + 199: 'Scotch terrier, Scottish terrier, Scottie', + 200: 'Tibetan terrier, chrysanthemum dog', + 201: 'silky terrier, Sydney silky', + 202: 'soft-coated wheaten terrier', + 203: 'West Highland white terrier', + 204: 'Lhasa, Lhasa apso', + 205: 'flat-coated retriever', + 206: 'curly-coated retriever', + 207: 'golden retriever', + 208: 'Labrador retriever', + 209: 'Chesapeake Bay retriever', + 210: 'German short-haired pointer', + 211: 'vizsla, Hungarian pointer', + 212: 'English setter', + 213: 'Irish setter, red setter', + 214: 'Gordon setter', + 215: 'Brittany spaniel', + 216: 'clumber, clumber spaniel', + 217: 'English springer, English springer spaniel', + 218: 'Welsh springer spaniel', + 219: 'cocker spaniel, English cocker spaniel, cocker', + 220: 'Sussex spaniel', + 221: 'Irish water spaniel', + 222: 'kuvasz', + 223: 'schipperke', + 224: 'groenendael', + 225: 'malinois', + 226: 'briard', + 227: 'kelpie', + 228: 'komondor', + 229: 'Old English sheepdog, bobtail', + 230: 'Shetland sheepdog, Shetland sheep dog, Shetland', + 231: 'collie', + 232: 'Border collie', + 233: 'Bouvier des Flandres, Bouviers des Flandres', + 234: 'Rottweiler', + 235: 'German shepherd, German shepherd dog, German police dog, alsatian', + 236: 'Doberman, Doberman pinscher', + 237: 'miniature pinscher', + 238: 'Greater Swiss Mountain dog', + 239: 'Bernese mountain dog', + 240: 'Appenzeller', + 241: 'EntleBucher', + 242: 'boxer', + 243: 'bull mastiff', + 244: 'Tibetan mastiff', + 245: 'French bulldog', + 246: 'Great Dane', + 247: 'Saint Bernard, St Bernard', + 248: 'Eskimo dog, husky', + 249: 'malamute, malemute, Alaskan malamute', + 250: 'Siberian husky', + 251: 'dalmatian, coach dog, carriage dog', + 252: 'affenpinscher, monkey pinscher, monkey dog', + 253: 'basenji', + 254: 'pug, pug-dog', + 255: 'Leonberg', + 256: 'Newfoundland, Newfoundland dog', + 257: 'Great Pyrenees', + 258: 'Samoyed, Samoyede', + 259: 'Pomeranian', + 260: 'chow, chow chow', + 261: 'keeshond', + 262: 'Brabancon griffon', + 263: 'Pembroke, Pembroke Welsh corgi', + 264: 'Cardigan, Cardigan Welsh corgi', + 265: 'toy poodle', + 266: 'miniature poodle', + 267: 'standard poodle', + 268: 'Mexican hairless', + 269: 'timber wolf, grey wolf, gray wolf, Canis lupus', + 270: 'white wolf, Arctic wolf, Canis lupus tundrarum', + 271: 'red wolf, maned wolf, Canis rufus, Canis niger', + 272: 'coyote, prairie wolf, brush wolf, Canis latrans', + 273: 'dingo, warrigal, warragal, Canis dingo', + 274: 'dhole, Cuon alpinus', + 275: 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus', + 276: 'hyena, hyaena', + 277: 'red fox, Vulpes vulpes', + 278: 'kit fox, Vulpes macrotis', + 279: 'Arctic fox, white fox, Alopex lagopus', + 280: 'grey fox, gray fox, Urocyon cinereoargenteus', + 281: 'tabby, tabby cat', + 282: 'tiger cat', + 283: 'Persian cat', + 284: 'Siamese cat, Siamese', + 285: 'Egyptian cat', + 286: 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor', + 287: 'lynx, catamount', + 288: 'leopard, Panthera pardus', + 289: 'snow leopard, ounce, Panthera uncia', + 290: 'jaguar, panther, Panthera onca, Felis onca', + 291: 'lion, king of beasts, Panthera leo', + 292: 'tiger, Panthera tigris', + 293: 'cheetah, chetah, Acinonyx jubatus', + 294: 'brown bear, bruin, Ursus arctos', + 295: 'American black bear, black bear, Ursus americanus, Euarctos americanus', + 296: 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus', + 297: 'sloth bear, Melursus ursinus, Ursus ursinus', + 298: 'mongoose', + 299: 'meerkat, mierkat', + 300: 'tiger beetle', + 301: 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle', + 302: 'ground beetle, carabid beetle', + 303: 'long-horned beetle, longicorn, longicorn beetle', + 304: 'leaf beetle, chrysomelid', + 305: 'dung beetle', + 306: 'rhinoceros beetle', + 307: 'weevil', + 308: 'fly', + 309: 'bee', + 310: 'ant, emmet, pismire', + 311: 'grasshopper, hopper', + 312: 'cricket', + 313: 'walking stick, walkingstick, stick insect', + 314: 'cockroach, roach', + 315: 'mantis, mantid', + 316: 'cicada, cicala', + 317: 'leafhopper', + 318: 'lacewing, lacewing fly', + 319: "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk", + 320: 'damselfly', + 321: 'admiral', + 322: 'ringlet, ringlet butterfly', + 323: 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus', + 324: 'cabbage butterfly', + 325: 'sulphur butterfly, sulfur butterfly', + 326: 'lycaenid, lycaenid butterfly', + 327: 'starfish, sea star', + 328: 'sea urchin', + 329: 'sea cucumber, holothurian', + 330: 'wood rabbit, cottontail, cottontail rabbit', + 331: 'hare', + 332: 'Angora, Angora rabbit', + 333: 'hamster', + 334: 'porcupine, hedgehog', + 335: 'fox squirrel, eastern fox squirrel, Sciurus niger', + 336: 'marmot', + 337: 'beaver', + 338: 'guinea pig, Cavia cobaya', + 339: 'sorrel', + 340: 'zebra', + 341: 'hog, pig, grunter, squealer, Sus scrofa', + 342: 'wild boar, boar, Sus scrofa', + 343: 'warthog', + 344: 'hippopotamus, hippo, river horse, Hippopotamus amphibius', + 345: 'ox', + 346: 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis', + 347: 'bison', + 348: 'ram, tup', + 349: 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis', + 350: 'ibex, Capra ibex', + 351: 'hartebeest', + 352: 'impala, Aepyceros melampus', + 353: 'gazelle', + 354: 'Arabian camel, dromedary, Camelus dromedarius', + 355: 'llama', + 356: 'weasel', + 357: 'mink', + 358: 'polecat, fitch, foulmart, foumart, Mustela putorius', + 359: 'black-footed ferret, ferret, Mustela nigripes', + 360: 'otter', + 361: 'skunk, polecat, wood pussy', + 362: 'badger', + 363: 'armadillo', + 364: 'three-toed sloth, ai, Bradypus tridactylus', + 365: 'orangutan, orang, orangutang, Pongo pygmaeus', + 366: 'gorilla, Gorilla gorilla', + 367: 'chimpanzee, chimp, Pan troglodytes', + 368: 'gibbon, Hylobates lar', + 369: 'siamang, Hylobates syndactylus, Symphalangus syndactylus', + 370: 'guenon, guenon monkey', + 371: 'patas, hussar monkey, Erythrocebus patas', + 372: 'baboon', + 373: 'macaque', + 374: 'langur', + 375: 'colobus, colobus monkey', + 376: 'proboscis monkey, Nasalis larvatus', + 377: 'marmoset', + 378: 'capuchin, ringtail, Cebus capucinus', + 379: 'howler monkey, howler', + 380: 'titi, titi monkey', + 381: 'spider monkey, Ateles geoffroyi', + 382: 'squirrel monkey, Saimiri sciureus', + 383: 'Madagascar cat, ring-tailed lemur, Lemur catta', + 384: 'indri, indris, Indri indri, Indri brevicaudatus', + 385: 'Indian elephant, Elephas maximus', + 386: 'African elephant, Loxodonta africana', + 387: 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens', + 388: 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca', + 389: 'barracouta, snoek', + 390: 'eel', + 391: 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch', + 392: 'rock beauty, Holocanthus tricolor', + 393: 'anemone fish', + 394: 'sturgeon', + 395: 'gar, garfish, garpike, billfish, Lepisosteus osseus', + 396: 'lionfish', + 397: 'puffer, pufferfish, blowfish, globefish', + 398: 'abacus', + 399: 'abaya', + 400: "academic gown, academic robe, judge's robe", + 401: 'accordion, piano accordion, squeeze box', + 402: 'acoustic guitar', + 403: 'aircraft carrier, carrier, flattop, attack aircraft carrier', + 404: 'airliner', + 405: 'airship, dirigible', + 406: 'altar', + 407: 'ambulance', + 408: 'amphibian, amphibious vehicle', + 409: 'analog clock', + 410: 'apiary, bee house', + 411: 'apron', + 412: 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin', + 413: 'assault rifle, assault gun', + 414: 'backpack, back pack, knapsack, packsack, rucksack, haversack', + 415: 'bakery, bakeshop, bakehouse', + 416: 'balance beam, beam', + 417: 'balloon', + 418: 'ballpoint, ballpoint pen, ballpen, Biro', + 419: 'Band Aid', + 420: 'banjo', + 421: 'bannister, banister, balustrade, balusters, handrail', + 422: 'barbell', + 423: 'barber chair', + 424: 'barbershop', + 425: 'barn', + 426: 'barometer', + 427: 'barrel, cask', + 428: 'barrow, garden cart, lawn cart, wheelbarrow', + 429: 'baseball', + 430: 'basketball', + 431: 'bassinet', + 432: 'bassoon', + 433: 'bathing cap, swimming cap', + 434: 'bath towel', + 435: 'bathtub, bathing tub, bath, tub', + 436: 'beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon', + 437: 'beacon, lighthouse, beacon light, pharos', + 438: 'beaker', + 439: 'bearskin, busby, shako', + 440: 'beer bottle', + 441: 'beer glass', + 442: 'bell cote, bell cot', + 443: 'bib', + 444: 'bicycle-built-for-two, tandem bicycle, tandem', + 445: 'bikini, two-piece', + 446: 'binder, ring-binder', + 447: 'binoculars, field glasses, opera glasses', + 448: 'birdhouse', + 449: 'boathouse', + 450: 'bobsled, bobsleigh, bob', + 451: 'bolo tie, bolo, bola tie, bola', + 452: 'bonnet, poke bonnet', + 453: 'bookcase', + 454: 'bookshop, bookstore, bookstall', + 455: 'bottlecap', + 456: 'bow', + 457: 'bow tie, bow-tie, bowtie', + 458: 'brass, memorial tablet, plaque', + 459: 'brassiere, bra, bandeau', + 460: 'breakwater, groin, groyne, mole, bulwark, seawall, jetty', + 461: 'breastplate, aegis, egis', + 462: 'broom', + 463: 'bucket, pail', + 464: 'buckle', + 465: 'bulletproof vest', + 466: 'bullet train, bullet', + 467: 'butcher shop, meat market', + 468: 'cab, hack, taxi, taxicab', + 469: 'caldron, cauldron', + 470: 'candle, taper, wax light', + 471: 'cannon', + 472: 'canoe', + 473: 'can opener, tin opener', + 474: 'cardigan', + 475: 'car mirror', + 476: 'carousel, carrousel, merry-go-round, roundabout, whirligig', + 477: "carpenter's kit, tool kit", + 478: 'carton', + 479: 'car wheel', + 480: 'cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM', + 481: 'cassette', + 482: 'cassette player', + 483: 'castle', + 484: 'catamaran', + 485: 'CD player', + 486: 'cello, violoncello', + 487: 'cellular telephone, cellular phone, cellphone, cell, mobile phone', + 488: 'chain', + 489: 'chainlink fence', + 490: 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour', + 491: 'chain saw, chainsaw', + 492: 'chest', + 493: 'chiffonier, commode', + 494: 'chime, bell, gong', + 495: 'china cabinet, china closet', + 496: 'Christmas stocking', + 497: 'church, church building', + 498: 'cinema, movie theater, movie theatre, movie house, picture palace', + 499: 'cleaver, meat cleaver, chopper', + 500: 'cliff dwelling', + 501: 'cloak', + 502: 'clog, geta, patten, sabot', + 503: 'cocktail shaker', + 504: 'coffee mug', + 505: 'coffeepot', + 506: 'coil, spiral, volute, whorl, helix', + 507: 'combination lock', + 508: 'computer keyboard, keypad', + 509: 'confectionery, confectionary, candy store', + 510: 'container ship, containership, container vessel', + 511: 'convertible', + 512: 'corkscrew, bottle screw', + 513: 'cornet, horn, trumpet, trump', + 514: 'cowboy boot', + 515: 'cowboy hat, ten-gallon hat', + 516: 'cradle', + 517: 'crane', + 518: 'crash helmet', + 519: 'crate', + 520: 'crib, cot', + 521: 'Crock Pot', + 522: 'croquet ball', + 523: 'crutch', + 524: 'cuirass', + 525: 'dam, dike, dyke', + 526: 'desk', + 527: 'desktop computer', + 528: 'dial telephone, dial phone', + 529: 'diaper, nappy, napkin', + 530: 'digital clock', + 531: 'digital watch', + 532: 'dining table, board', + 533: 'dishrag, dishcloth', + 534: 'dishwasher, dish washer, dishwashing machine', + 535: 'disk brake, disc brake', + 536: 'dock, dockage, docking facility', + 537: 'dogsled, dog sled, dog sleigh', + 538: 'dome', + 539: 'doormat, welcome mat', + 540: 'drilling platform, offshore rig', + 541: 'drum, membranophone, tympan', + 542: 'drumstick', + 543: 'dumbbell', + 544: 'Dutch oven', + 545: 'electric fan, blower', + 546: 'electric guitar', + 547: 'electric locomotive', + 548: 'entertainment center', + 549: 'envelope', + 550: 'espresso maker', + 551: 'face powder', + 552: 'feather boa, boa', + 553: 'file, file cabinet, filing cabinet', + 554: 'fireboat', + 555: 'fire engine, fire truck', + 556: 'fire screen, fireguard', + 557: 'flagpole, flagstaff', + 558: 'flute, transverse flute', + 559: 'folding chair', + 560: 'football helmet', + 561: 'forklift', + 562: 'fountain', + 563: 'fountain pen', + 564: 'four-poster', + 565: 'freight car', + 566: 'French horn, horn', + 567: 'frying pan, frypan, skillet', + 568: 'fur coat', + 569: 'garbage truck, dustcart', + 570: 'gasmask, respirator, gas helmet', + 571: 'gas pump, gasoline pump, petrol pump, island dispenser', + 572: 'goblet', + 573: 'go-kart', + 574: 'golf ball', + 575: 'golfcart, golf cart', + 576: 'gondola', + 577: 'gong, tam-tam', + 578: 'gown', + 579: 'grand piano, grand', + 580: 'greenhouse, nursery, glasshouse', + 581: 'grille, radiator grille', + 582: 'grocery store, grocery, food market, market', + 583: 'guillotine', + 584: 'hair slide', + 585: 'hair spray', + 586: 'half track', + 587: 'hammer', + 588: 'hamper', + 589: 'hand blower, blow dryer, blow drier, hair dryer, hair drier', + 590: 'hand-held computer, hand-held microcomputer', + 591: 'handkerchief, hankie, hanky, hankey', + 592: 'hard disc, hard disk, fixed disk', + 593: 'harmonica, mouth organ, harp, mouth harp', + 594: 'harp', + 595: 'harvester, reaper', + 596: 'hatchet', + 597: 'holster', + 598: 'home theater, home theatre', + 599: 'honeycomb', + 600: 'hook, claw', + 601: 'hoopskirt, crinoline', + 602: 'horizontal bar, high bar', + 603: 'horse cart, horse-cart', + 604: 'hourglass', + 605: 'iPod', + 606: 'iron, smoothing iron', + 607: "jack-o'-lantern", + 608: 'jean, blue jean, denim', + 609: 'jeep, landrover', + 610: 'jersey, T-shirt, tee shirt', + 611: 'jigsaw puzzle', + 612: 'jinrikisha, ricksha, rickshaw', + 613: 'joystick', + 614: 'kimono', + 615: 'knee pad', + 616: 'knot', + 617: 'lab coat, laboratory coat', + 618: 'ladle', + 619: 'lampshade, lamp shade', + 620: 'laptop, laptop computer', + 621: 'lawn mower, mower', + 622: 'lens cap, lens cover', + 623: 'letter opener, paper knife, paperknife', + 624: 'library', + 625: 'lifeboat', + 626: 'lighter, light, igniter, ignitor', + 627: 'limousine, limo', + 628: 'liner, ocean liner', + 629: 'lipstick, lip rouge', + 630: 'Loafer', + 631: 'lotion', + 632: 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker system', + 633: "loupe, jeweler's loupe", + 634: 'lumbermill, sawmill', + 635: 'magnetic compass', + 636: 'mailbag, postbag', + 637: 'mailbox, letter box', + 638: 'maillot', + 639: 'maillot, tank suit', + 640: 'manhole cover', + 641: 'maraca', + 642: 'marimba, xylophone', + 643: 'mask', + 644: 'matchstick', + 645: 'maypole', + 646: 'maze, labyrinth', + 647: 'measuring cup', + 648: 'medicine chest, medicine cabinet', + 649: 'megalith, megalithic structure', + 650: 'microphone, mike', + 651: 'microwave, microwave oven', + 652: 'military uniform', + 653: 'milk can', + 654: 'minibus', + 655: 'miniskirt, mini', + 656: 'minivan', + 657: 'missile', + 658: 'mitten', + 659: 'mixing bowl', + 660: 'mobile home, manufactured home', + 661: 'Model T', + 662: 'modem', + 663: 'monastery', + 664: 'monitor', + 665: 'moped', + 666: 'mortar', + 667: 'mortarboard', + 668: 'mosque', + 669: 'mosquito net', + 670: 'motor scooter, scooter', + 671: 'mountain bike, all-terrain bike, off-roader', + 672: 'mountain tent', + 673: 'mouse, computer mouse', + 674: 'mousetrap', + 675: 'moving van', + 676: 'muzzle', + 677: 'nail', + 678: 'neck brace', + 679: 'necklace', + 680: 'nipple', + 681: 'notebook, notebook computer', + 682: 'obelisk', + 683: 'oboe, hautboy, hautbois', + 684: 'ocarina, sweet potato', + 685: 'odometer, hodometer, mileometer, milometer', + 686: 'oil filter', + 687: 'organ, pipe organ', + 688: 'oscilloscope, scope, cathode-ray oscilloscope, CRO', + 689: 'overskirt', + 690: 'oxcart', + 691: 'oxygen mask', + 692: 'packet', + 693: 'paddle, boat paddle', + 694: 'paddlewheel, paddle wheel', + 695: 'padlock', + 696: 'paintbrush', + 697: "pajama, pyjama, pj's, jammies", + 698: 'palace', + 699: 'panpipe, pandean pipe, syrinx', + 700: 'paper towel', + 701: 'parachute, chute', + 702: 'parallel bars, bars', + 703: 'park bench', + 704: 'parking meter', + 705: 'passenger car, coach, carriage', + 706: 'patio, terrace', + 707: 'pay-phone, pay-station', + 708: 'pedestal, plinth, footstall', + 709: 'pencil box, pencil case', + 710: 'pencil sharpener', + 711: 'perfume, essence', + 712: 'Petri dish', + 713: 'photocopier', + 714: 'pick, plectrum, plectron', + 715: 'pickelhaube', + 716: 'picket fence, paling', + 717: 'pickup, pickup truck', + 718: 'pier', + 719: 'piggy bank, penny bank', + 720: 'pill bottle', + 721: 'pillow', + 722: 'ping-pong ball', + 723: 'pinwheel', + 724: 'pirate, pirate ship', + 725: 'pitcher, ewer', + 726: "plane, carpenter's plane, woodworking plane", + 727: 'planetarium', + 728: 'plastic bag', + 729: 'plate rack', + 730: 'plow, plough', + 731: "plunger, plumber's helper", + 732: 'Polaroid camera, Polaroid Land camera', + 733: 'pole', + 734: 'police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria', + 735: 'poncho', + 736: 'pool table, billiard table, snooker table', + 737: 'pop bottle, soda bottle', + 738: 'pot, flowerpot', + 739: "potter's wheel", + 740: 'power drill', + 741: 'prayer rug, prayer mat', + 742: 'printer', + 743: 'prison, prison house', + 744: 'projectile, missile', + 745: 'projector', + 746: 'puck, hockey puck', + 747: 'punching bag, punch bag, punching ball, punchball', + 748: 'purse', + 749: 'quill, quill pen', + 750: 'quilt, comforter, comfort, puff', + 751: 'racer, race car, racing car', + 752: 'racket, racquet', + 753: 'radiator', + 754: 'radio, wireless', + 755: 'radio telescope, radio reflector', + 756: 'rain barrel', + 757: 'recreational vehicle, RV, R.V.', + 758: 'reel', + 759: 'reflex camera', + 760: 'refrigerator, icebox', + 761: 'remote control, remote', + 762: 'restaurant, eating house, eating place, eatery', + 763: 'revolver, six-gun, six-shooter', + 764: 'rifle', + 765: 'rocking chair, rocker', + 766: 'rotisserie', + 767: 'rubber eraser, rubber, pencil eraser', + 768: 'rugby ball', + 769: 'rule, ruler', + 770: 'running shoe', + 771: 'safe', + 772: 'safety pin', + 773: 'saltshaker, salt shaker', + 774: 'sandal', + 775: 'sarong', + 776: 'sax, saxophone', + 777: 'scabbard', + 778: 'scale, weighing machine', + 779: 'school bus', + 780: 'schooner', + 781: 'scoreboard', + 782: 'screen, CRT screen', + 783: 'screw', + 784: 'screwdriver', + 785: 'seat belt, seatbelt', + 786: 'sewing machine', + 787: 'shield, buckler', + 788: 'shoe shop, shoe-shop, shoe store', + 789: 'shoji', + 790: 'shopping basket', + 791: 'shopping cart', + 792: 'shovel', + 793: 'shower cap', + 794: 'shower curtain', + 795: 'ski', + 796: 'ski mask', + 797: 'sleeping bag', + 798: 'slide rule, slipstick', + 799: 'sliding door', + 800: 'slot, one-armed bandit', + 801: 'snorkel', + 802: 'snowmobile', + 803: 'snowplow, snowplough', + 804: 'soap dispenser', + 805: 'soccer ball', + 806: 'sock', + 807: 'solar dish, solar collector, solar furnace', + 808: 'sombrero', + 809: 'soup bowl', + 810: 'space bar', + 811: 'space heater', + 812: 'space shuttle', + 813: 'spatula', + 814: 'speedboat', + 815: "spider web, spider's web", + 816: 'spindle', + 817: 'sports car, sport car', + 818: 'spotlight, spot', + 819: 'stage', + 820: 'steam locomotive', + 821: 'steel arch bridge', + 822: 'steel drum', + 823: 'stethoscope', + 824: 'stole', + 825: 'stone wall', + 826: 'stopwatch, stop watch', + 827: 'stove', + 828: 'strainer', + 829: 'streetcar, tram, tramcar, trolley, trolley car', + 830: 'stretcher', + 831: 'studio couch, day bed', + 832: 'stupa, tope', + 833: 'submarine, pigboat, sub, U-boat', + 834: 'suit, suit of clothes', + 835: 'sundial', + 836: 'sunglass', + 837: 'sunglasses, dark glasses, shades', + 838: 'sunscreen, sunblock, sun blocker', + 839: 'suspension bridge', + 840: 'swab, swob, mop', + 841: 'sweatshirt', + 842: 'swimming trunks, bathing trunks', + 843: 'swing', + 844: 'switch, electric switch, electrical switch', + 845: 'syringe', + 846: 'table lamp', + 847: 'tank, army tank, armored combat vehicle, armoured combat vehicle', + 848: 'tape player', + 849: 'teapot', + 850: 'teddy, teddy bear', + 851: 'television, television system', + 852: 'tennis ball', + 853: 'thatch, thatched roof', + 854: 'theater curtain, theatre curtain', + 855: 'thimble', + 856: 'thresher, thrasher, threshing machine', + 857: 'throne', + 858: 'tile roof', + 859: 'toaster', + 860: 'tobacco shop, tobacconist shop, tobacconist', + 861: 'toilet seat', + 862: 'torch', + 863: 'totem pole', + 864: 'tow truck, tow car, wrecker', + 865: 'toyshop', + 866: 'tractor', + 867: 'trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi', + 868: 'tray', + 869: 'trench coat', + 870: 'tricycle, trike, velocipede', + 871: 'trimaran', + 872: 'tripod', + 873: 'triumphal arch', + 874: 'trolleybus, trolley coach, trackless trolley', + 875: 'trombone', + 876: 'tub, vat', + 877: 'turnstile', + 878: 'typewriter keyboard', + 879: 'umbrella', + 880: 'unicycle, monocycle', + 881: 'upright, upright piano', + 882: 'vacuum, vacuum cleaner', + 883: 'vase', + 884: 'vault', + 885: 'velvet', + 886: 'vending machine', + 887: 'vestment', + 888: 'viaduct', + 889: 'violin, fiddle', + 890: 'volleyball', + 891: 'waffle iron', + 892: 'wall clock', + 893: 'wallet, billfold, notecase, pocketbook', + 894: 'wardrobe, closet, press', + 895: 'warplane, military plane', + 896: 'washbasin, handbasin, washbowl, lavabo, wash-hand basin', + 897: 'washer, automatic washer, washing machine', + 898: 'water bottle', + 899: 'water jug', + 900: 'water tower', + 901: 'whiskey jug', + 902: 'whistle', + 903: 'wig', + 904: 'window screen', + 905: 'window shade', + 906: 'Windsor tie', + 907: 'wine bottle', + 908: 'wing', + 909: 'wok', + 910: 'wooden spoon', + 911: 'wool, woolen, woollen', + 912: 'worm fence, snake fence, snake-rail fence, Virginia fence', + 913: 'wreck', + 914: 'yawl', + 915: 'yurt', + 916: 'web site, website, internet site, site', + 917: 'comic book', + 918: 'crossword puzzle, crossword', + 919: 'street sign', + 920: 'traffic light, traffic signal, stoplight', + 921: 'book jacket, dust cover, dust jacket, dust wrapper', + 922: 'menu', + 923: 'plate', + 924: 'guacamole', + 925: 'consomme', + 926: 'hot pot, hotpot', + 927: 'trifle', + 928: 'ice cream, icecream', + 929: 'ice lolly, lolly, lollipop, popsicle', + 930: 'French loaf', + 931: 'bagel, beigel', + 932: 'pretzel', + 933: 'cheeseburger', + 934: 'hotdog, hot dog, red hot', + 935: 'mashed potato', + 936: 'head cabbage', + 937: 'broccoli', + 938: 'cauliflower', + 939: 'zucchini, courgette', + 940: 'spaghetti squash', + 941: 'acorn squash', + 942: 'butternut squash', + 943: 'cucumber, cuke', + 944: 'artichoke, globe artichoke', + 945: 'bell pepper', + 946: 'cardoon', + 947: 'mushroom', + 948: 'Granny Smith', + 949: 'strawberry', + 950: 'orange', + 951: 'lemon', + 952: 'fig', + 953: 'pineapple, ananas', + 954: 'banana', + 955: 'jackfruit, jak, jack', + 956: 'custard apple', + 957: 'pomegranate', + 958: 'hay', + 959: 'carbonara', + 960: 'chocolate sauce, chocolate syrup', + 961: 'dough', + 962: 'meat loaf, meatloaf', + 963: 'pizza, pizza pie', + 964: 'potpie', + 965: 'burrito', + 966: 'red wine', + 967: 'espresso', + 968: 'cup', + 969: 'eggnog', + 970: 'alp', + 971: 'bubble', + 972: 'cliff, drop, drop-off', + 973: 'coral reef', + 974: 'geyser', + 975: 'lakeside, lakeshore', + 976: 'promontory, headland, head, foreland', + 977: 'sandbar, sand bar', + 978: 'seashore, coast, seacoast, sea-coast', + 979: 'valley, vale', + 980: 'volcano', + 981: 'ballplayer, baseball player', + 982: 'groom, bridegroom', + 983: 'scuba diver', + 984: 'rapeseed', + 985: 'daisy', + 986: "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum", + 987: 'corn', + 988: 'acorn', + 989: 'hip, rose hip, rosehip', + 990: 'buckeye, horse chestnut, conker', + 991: 'coral fungus', + 992: 'agaric', + 993: 'gyromitra', + 994: 'stinkhorn, carrion fungus', + 995: 'earthstar', + 996: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa', + 997: 'bolete', + 998: 'ear, spike, capitulum', + 999: 'toilet tissue, toilet paper, bathroom tissue'} \ No newline at end of file diff --git a/build/lib/gradio/inputs.py b/build/lib/gradio/inputs.py index 02a3e7c6eb..415f720bd4 100644 --- a/build/lib/gradio/inputs.py +++ b/build/lib/gradio/inputs.py @@ -1,9 +1,15 @@ +""" +This module defines various classes that can serve as the `input` to an interface. Each class must inherit from +`AbstractInput`, and each class must define a path to its template. All of the subclasses of `AbstractInput` are +automatically added to a registry, which allows them to be easily referenced in other parts of the code. +""" + from abc import ABC, abstractmethod import base64 -from PIL import Image +from gradio import preprocessing_utils from io import BytesIO import numpy as np -from gradio import preprocessing_utils +from PIL import Image class AbstractInput(ABC): """ @@ -12,84 +18,115 @@ class AbstractInput(ABC): """ def __init__(self, preprocessing_fn=None): + """ + :param preprocessing_fn: an optional preprocessing function that overrides the default + """ if preprocessing_fn is not None: - self._pre_process = preprocessing_fn + if not callable(preprocessing_fn): + raise ValueError('`preprocessing_fn` must be a callable function') + self.preprocess = preprocessing_fn super().__init__() @abstractmethod - def _get_template_path(self): + def get_template_path(self): """ All interfaces should define a method that returns the path to its template. """ pass @abstractmethod - def _pre_process(self): + def preprocess(self, inp): """ - All interfaces should define a method that returns the path to its template. + All interfaces should define a default preprocessing method """ pass class Sketchpad(AbstractInput): + def __init__(self, preprocessing_fn=None, image_width=28, image_height=28): + self.image_width = image_width + self.image_height = image_height + super().__init__(preprocessing_fn=preprocessing_fn) - def _get_template_path(self): + def get_template_path(self): return 'templates/sketchpad_input.html' - def _pre_process(self, imgstring): + def preprocess(self, inp): """ + Default preprocessing method for the SketchPad is to convert the sketch to black and white and resize 28x28 """ - content = imgstring.split(';')[1] + content = inp.split(';')[1] image_encoded = content.split(',')[1] - body = base64.decodebytes(image_encoded.encode('utf-8')) im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L') - im = preprocessing_utils.resize_and_crop(im, (28, 28)) - array = np.array(im).flatten().reshape(1, 28, 28, 1) + im = preprocessing_utils.resize_and_crop(im, (self.image_width, self.image_height)) + array = np.array(im).flatten().reshape(1, self.image_width, self.image_height, 1) return array class Webcam(AbstractInput): + def __init__(self, preprocessing_fn=None, image_width=224, image_height=224, num_channels=3): + self.image_width = image_width + self.image_height = image_height + self.num_channels = num_channels + super().__init__(preprocessing_fn=preprocessing_fn) - def _get_template_path(self): + def get_template_path(self): return 'templates/webcam_input.html' - def _pre_process(self, imgstring): + def preprocess(self, inp): """ + Default preprocessing method for is to convert the picture to black and white and resize to be 48x48 """ - content = imgstring.split(';')[1] + content = inp.split(';')[1] image_encoded = content.split(',')[1] - body = base64.decodebytes(image_encoded.encode('utf-8')) - im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L') - im = preprocessing_utils.resize_and_crop(im, (48, 48)) - array = np.array(im).flatten().reshape(1, 48, 48, 1) + im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('RGB') + im = preprocessing_utils.resize_and_crop(im, (self.image_width, self.image_height)) + array = np.array(im).flatten().reshape(1, self.image_width, self.image_height, self.num_channels) return array class Textbox(AbstractInput): - def _get_template_path(self): + def get_template_path(self): return 'templates/textbox_input.html' - def _pre_process(self, text): + def preprocess(self, inp): """ + By default, no pre-processing is applied to text. """ - return text + return inp + class ImageUpload(AbstractInput): + def __init__(self, preprocessing_fn=None, image_width=224, image_height=224, num_channels=3, image_mode='RGB', + scale = 1/127.5, shift = -1): + self.image_width = image_width + self.image_height = image_height + self.num_channels = num_channels + self.image_mode = image_mode + self.scale = scale + self.shift = shift + super().__init__(preprocessing_fn=preprocessing_fn) - def _get_template_path(self): + def get_template_path(self): return 'templates/image_upload_input.html' - def _pre_process(self, imgstring): + def preprocess(self, inp): """ + Default preprocessing method for is to convert the picture to black and white and resize to be 48x48 """ - content = imgstring.split(';')[1] + content = inp.split(';')[1] image_encoded = content.split(',')[1] - body = base64.decodebytes(image_encoded.encode('utf-8')) - im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L') - im = preprocessing_utils.resize_and_crop(im, (48, 48)) - array = np.array(im).flatten().reshape(1, 48, 48, 1) + im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert(self.image_mode) + im = preprocessing_utils.resize_and_crop(im, (self.image_width, self.image_height)) + im = np.array(im).flatten() + im = im * self.scale + self.shift + if self.num_channels is None: + array = im.reshape(1, self.image_width, self.image_height) + else: + array = im.reshape(1, self.image_width, self.image_height, self.num_channels) return array +# Automatically adds all subclasses of AbstractInput into a dictionary (keyed by class name) for easy referencing. registry = {cls.__name__.lower(): cls for cls in AbstractInput.__subclasses__()} diff --git a/build/lib/gradio/interface.py b/build/lib/gradio/interface.py index 91360dcc24..366cfb83b1 100644 --- a/build/lib/gradio/interface.py +++ b/build/lib/gradio/interface.py @@ -1,14 +1,15 @@ +''' +This is the core file in the `gradio` package, and defines the Interface class, including methods for constructing the +interface using the input and output types. +''' + import asyncio import websockets import nest_asyncio import webbrowser -import pkg_resources -from bs4 import BeautifulSoup -from gradio import inputs -from gradio import outputs +import gradio.inputs +import gradio.outputs from gradio import networking -import os -import shutil import tempfile nest_asyncio.apply() @@ -17,46 +18,53 @@ LOCALHOST_IP = '127.0.0.1' INITIAL_WEBSOCKET_PORT = 9200 TRY_NUM_PORTS = 100 -BASE_TEMPLATE = pkg_resources.resource_filename('gradio', 'templates/base_template.html') -JS_PATH_LIB = pkg_resources.resource_filename('gradio', 'js/') -CSS_PATH_LIB = pkg_resources.resource_filename('gradio', 'css/') -JS_PATH_TEMP = 'js/' -CSS_PATH_TEMP = 'css/' -TEMPLATE_TEMP = 'interface.html' -BASE_JS_FILE = 'js/all-io.js' - -class Interface(): +class Interface: """ + The Interface class represents a general input/output interface for a machine learning model. During construction, + the appropriate inputs and outputs """ # Dictionary in which each key is a valid `model_type` argument to constructor, and the value being the description. VALID_MODEL_TYPES = {'sklearn': 'sklearn model', 'keras': 'keras model', 'function': 'python function'} - def __init__(self, input, output, model, model_type=None, preprocessing_fn=None, postprocessing_fn=None): + def __init__(self, inputs, outputs, model, model_type=None, preprocessing_fns=None, postprocessing_fns=None, + verbose=True): """ - :param model_type: what kind of trained model, can be 'keras' or 'sklearn'. + :param inputs: a string or `AbstractInput` representing the input interface. + :param outputs: a string or `AbstractOutput` representing the output interface. :param model_obj: the model object, such as a sklearn classifier or keras model. - :param model_params: additional model parameters. + :param model_type: what kind of trained model, can be 'keras' or 'sklearn' or 'function'. Inferred if not + provided. + :param preprocessing_fns: an optional function that overrides the preprocessing function of the input interface. + :param postprocessing_fns: an optional function that overrides the postprocessing fn of the output interface. """ - self.input_interface = inputs.registry[input](preprocessing_fn) - self.output_interface = outputs.registry[output](postprocessing_fn) + if isinstance(inputs, str): + self.input_interface = gradio.inputs.registry[inputs.lower()](preprocessing_fns) + elif isinstance(inputs, gradio.inputs.AbstractInput): + self.input_interface = inputs + else: + raise ValueError('Input interface must be of type `str` or `AbstractInput`') + if isinstance(outputs, str): + self.output_interface = gradio.outputs.registry[outputs.lower()](postprocessing_fns) + elif isinstance(outputs, gradio.outputs.AbstractOutput): + self.output_interface = outputs + else: + raise ValueError('Output interface must be of type `str` or `AbstractOutput`') self.model_obj = model if model_type is None: model_type = self._infer_model_type(model) - if model_type is None: - raise ValueError("model_type could not be inferred, please specify parameter `model_type`") - else: + if verbose: print("Model type not explicitly identified, inferred to be: {}".format( - self.VALID_MODEL_TYPES[model_type])) + self.VALID_MODEL_TYPES[model_type])) elif not(model_type.lower() in self.VALID_MODEL_TYPES): ValueError('model_type must be one of: {}'.format(self.VALID_MODEL_TYPES)) self.model_type = model_type + self.verbose = verbose - def _infer_model_type(self, model): - if callable(model): - return 'function' - + @staticmethod + def _infer_model_type(model): + """ Helper method that attempts to identify the type of trained ML model.""" try: import sklearn if isinstance(model, sklearn.base.BaseEstimator): @@ -78,124 +86,100 @@ class Interface(): except ImportError: pass - return None + if callable(model): + return 'function' - def _build_template(self, temp_dir): - input_template_path = pkg_resources.resource_filename( - 'gradio', self.input_interface._get_template_path()) - output_template_path = pkg_resources.resource_filename( - 'gradio', self.output_interface._get_template_path()) - input_page = open(input_template_path) - output_page = open(output_template_path) - input_soup = BeautifulSoup(input_page.read(), features="html.parser") - output_soup = BeautifulSoup(output_page.read(), features="html.parser") - - all_io_page = open(BASE_TEMPLATE) - all_io_soup = BeautifulSoup(all_io_page.read(), features="html.parser") - input_tag = all_io_soup.find("div", {"id": "input"}) - output_tag = all_io_soup.find("div", {"id": "output"}) - - input_tag.replace_with(input_soup) - output_tag.replace_with(output_soup) - - f = open(os.path.join(temp_dir, TEMPLATE_TEMP), "w") - f.write(str(all_io_soup.prettify)) - - self._copy_files(JS_PATH_LIB, os.path.join(temp_dir, JS_PATH_TEMP)) - self._copy_files(CSS_PATH_LIB, os.path.join(temp_dir, CSS_PATH_TEMP)) - return - - def _copy_files(self, src_dir, dest_dir): - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - src_files = os.listdir(src_dir) - for file_name in src_files: - full_file_name = os.path.join(src_dir, file_name) - if os.path.isfile(full_file_name): - shutil.copy(full_file_name, dest_dir) - - def _set_socket_url_in_js(self, temp_dir, socket_url): - with open(os.path.join(temp_dir, BASE_JS_FILE)) as fin: - lines = fin.readlines() - lines[0] = 'var NGROK_URL = "{}"\n'.format(socket_url.replace('http', 'ws')) - - with open(os.path.join(temp_dir, BASE_JS_FILE), 'w') as fout: - for line in lines: - fout.write(line) - - def _set_socket_port_in_js(self, temp_dir, socket_port): - with open(os.path.join(temp_dir, BASE_JS_FILE)) as fin: - lines = fin.readlines() - lines[1] = 'var SOCKET_PORT = {}\n'.format(socket_port) - - with open(os.path.join(temp_dir, BASE_JS_FILE), 'w') as fout: - for line in lines: - fout.write(line) - - def predict(self, array): - if self.model_type=='sklearn': - return self.model_obj.predict(array) - elif self.model_type=='keras': - return self.model_obj.predict(array) - elif self.model_type=='function': - return self.model_obj(array) - else: - ValueError('model_type must be one of: {}'.format(self.VALID_MODEL_TYPES)) + raise ValueError("model_type could not be inferred, please specify parameter `model_type`") async def communicate(self, websocket, path): """ - Method that defines how this interface communicates with the websocket. - :param websocket: a Websocket object used to communicate with the interface frontend - :param path: ignored + Method that defines how this interface should communicates with the websocket. (1) When an input is received by + the websocket, it is passed into the input interface and preprocssed. (2) Then the model is called to make a + prediction. (3) Finally, the prediction is postprocessed to get something to be displayed by the output. + :param websocket: a Websocket server used to communicate with the interface frontend + :param path: not used, but required for compliance with websocket library """ while True: try: msg = await websocket.recv() - processed_input = self.input_interface._pre_process(msg) + processed_input = self.input_interface.preprocess(msg) prediction = self.predict(processed_input) - processed_output = self.output_interface._post_process(prediction) + processed_output = self.output_interface.postprocess(prediction) await websocket.send(str(processed_output)) except websockets.exceptions.ConnectionClosed: pass + # except Exception as e: + # print(e) - def launch(self, share_link=False, verbose=True): + def predict(self, preprocessed_input): """ - Standard method shared by interfaces that launches a websocket at a specified IP address. + Method that calls the relevant method of the model object to make a prediction. + :param preprocessed_input: the preprocessed input returned by the input interface + """ + if self.model_type=='sklearn': + return self.model_obj.predict(preprocessed_input) + elif self.model_type=='keras': + return self.model_obj.predict(preprocessed_input) + elif self.model_type=='function': + return self.model_obj(preprocessed_input) + else: + ValueError('model_type must be one of: {}'.format(self.VALID_MODEL_TYPES)) + + def launch(self, inline=None, browser=None, share=False): + """ + Standard method shared by interfaces that creates the interface and sets up a websocket to communicate with it. + :param share: boolean. If True, then a share link is generated using ngrok is displayed to the user. """ output_directory = tempfile.mkdtemp() + + # Set up a port to serve the directory containing the static files with interface. server_port = networking.start_simple_server(output_directory) path_to_server = 'http://localhost:{}/'.format(server_port) - self._build_template(output_directory) + networking.build_template(output_directory, self.input_interface, self.output_interface) - ports_in_use = networking.get_ports_in_use(INITIAL_WEBSOCKET_PORT, INITIAL_WEBSOCKET_PORT + TRY_NUM_PORTS) - for i in range(TRY_NUM_PORTS): - if not ((INITIAL_WEBSOCKET_PORT + i) in ports_in_use): - break - else: - raise OSError("All ports from {} to {} are in use. Please close a port.".format( - INITIAL_WEBSOCKET_PORT, INITIAL_WEBSOCKET_PORT + TRY_NUM_PORTS)) - - start_server = websockets.serve(self.communicate, LOCALHOST_IP, INITIAL_WEBSOCKET_PORT + i) - self._set_socket_port_in_js(output_directory, INITIAL_WEBSOCKET_PORT + i) - if verbose: + # Set up a port to serve a websocket that sets up the communication between the front-end and model. + websocket_port = networking.get_first_available_port( + INITIAL_WEBSOCKET_PORT, INITIAL_WEBSOCKET_PORT + TRY_NUM_PORTS) + start_server = websockets.serve(self.communicate, LOCALHOST_IP, websocket_port) + networking.set_socket_port_in_js(output_directory, websocket_port) # sets the websocket port in the JS file. + if self.verbose: print("NOTE: Gradio is in beta stage, please report all bugs to: a12d@stanford.edu") - print("Model available locally at: {}".format(path_to_server + TEMPLATE_TEMP)) + print("Model is running locally at: {}".format(path_to_server + networking.TEMPLATE_TEMP)) - if share_link: - networking.kill_processes([4040, 4041]) - site_ngrok_url = networking.setup_ngrok(server_port) - socket_ngrok_url = networking.setup_ngrok(INITIAL_WEBSOCKET_PORT, api_url=networking.NGROK_TUNNELS_API_URL2) - self._set_socket_url_in_js(output_directory, socket_ngrok_url) - if verbose: - print("Model available publicly for 8 hours at: {}".format(site_ngrok_url + '/' + TEMPLATE_TEMP)) + if share: + site_ngrok_url = networking.setup_ngrok(server_port, websocket_port, output_directory) + if self.verbose: + print("Model available publicly for 8 hours at: {}".format( + site_ngrok_url + '/' + networking.TEMPLATE_TEMP)) else: - if verbose: - print("To create a public link, set `share_link=True` in the argument to `launch()`") + if self.verbose: + print("To create a public link, set `share=True` in the argument to `launch()`") + site_ngrok_url = None + # Keep the server running in the background. asyncio.get_event_loop().run_until_complete(start_server) try: asyncio.get_event_loop().run_forever() except RuntimeError: # Runtime errors are thrown in jupyter notebooks because of async. pass - webbrowser.open(path_to_server + TEMPLATE_TEMP) + if inline is None: + try: # Check if running interactively using ipython. + _ = get_ipython() + inline = True + if browser is None: + browser = False + except NameError: + inline = False + if browser is None: + browser = True + else: + if browser is None: + browser = False + if browser: + webbrowser.open(path_to_server + networking.TEMPLATE_TEMP) # Open a browser tab with the interface. + if inline: + from IPython.display import IFrame + display(IFrame(path_to_server + networking.TEMPLATE_TEMP, width=1000, height=500)) + + return path_to_server + networking.TEMPLATE_TEMP, site_ngrok_url \ No newline at end of file diff --git a/build/lib/gradio/networking.py b/build/lib/gradio/networking.py index 2ace36072b..7183b57510 100644 --- a/build/lib/gradio/networking.py +++ b/build/lib/gradio/networking.py @@ -1,3 +1,7 @@ +''' +Defines helper methods useful for setting up ports, launching servers, and handling `ngrok` +''' + import subprocess import requests import zipfile @@ -5,21 +9,31 @@ import io import sys import os import socket -from psutil import process_iter, AccessDenied +from psutil import process_iter, AccessDenied, NoSuchProcess from signal import SIGTERM # or SIGKILL import threading from http.server import HTTPServer as BaseHTTPServer, SimpleHTTPRequestHandler import stat from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry +import pkg_resources +from bs4 import BeautifulSoup +from distutils import dir_util -INITIAL_PORT_VALUE = 7860 -TRY_NUM_PORTS = 100 +INITIAL_PORT_VALUE = 7860 # The http server will try to open on port 7860. If not available, 7861, 7862, etc. +TRY_NUM_PORTS = 100 # Number of ports to try before giving up and throwing an exception. LOCALHOST_NAME = 'localhost' -LOCALHOST_PREFIX = 'localhost:' NGROK_TUNNELS_API_URL = "http://localhost:4040/api/tunnels" # TODO(this should be captured from output) NGROK_TUNNELS_API_URL2 = "http://localhost:4041/api/tunnels" # TODO(this should be captured from output) + +BASE_TEMPLATE = pkg_resources.resource_filename('gradio', 'templates/base_template.html') +STATIC_PATH_LIB = pkg_resources.resource_filename('gradio', 'static/') +STATIC_PATH_TEMP = 'static/' +TEMPLATE_TEMP = 'interface.html' +BASE_JS_FILE = 'static/js/all-io.js' + + NGROK_ZIP_URLS = { "linux": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip", "darwin": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip", @@ -27,48 +41,83 @@ NGROK_ZIP_URLS = { } -def get_ports_in_use(start, stop): - ports_in_use = [] - for port in range(start, stop): +def build_template(temp_dir, input_interface, output_interface): + """ + Builds a complete HTML template with supporting JS and CSS files in a given directory. + :param temp_dir: string with path to temp directory in which the template should be built + :param input_interface: an AbstractInput object which includes is used to get the input template + :param output_interface: an AbstractInput object which includes is used to get the input template + """ + input_template_path = pkg_resources.resource_filename('gradio', input_interface.get_template_path()) + output_template_path = pkg_resources.resource_filename('gradio', output_interface.get_template_path()) + input_page = open(input_template_path) + output_page = open(output_template_path) + input_soup = BeautifulSoup(input_page.read(), features="html.parser") + output_soup = BeautifulSoup(output_page.read(), features="html.parser") + + all_io_page = open(BASE_TEMPLATE) + all_io_soup = BeautifulSoup(all_io_page.read(), features="html.parser") + input_tag = all_io_soup.find("div", {"id": "input"}) + output_tag = all_io_soup.find("div", {"id": "output"}) + + input_tag.replace_with(input_soup) + output_tag.replace_with(output_soup) + + f = open(os.path.join(temp_dir, TEMPLATE_TEMP), "w") + f.write(str(all_io_soup)) + + copy_files(STATIC_PATH_LIB, os.path.join(temp_dir, STATIC_PATH_TEMP)) + + +def copy_files(src_dir, dest_dir): + """ + Copies all the files from one directory to another + :param src_dir: string path to source directory + :param dest_dir: string path to destination directory + """ + dir_util.copy_tree(src_dir, dest_dir) + + +#TODO(abidlabs): Handle the http vs. https issue that sometimes happens (a ws cannot be loaded from an https page) +def set_socket_url_in_js(temp_dir, socket_url): + with open(os.path.join(temp_dir, BASE_JS_FILE)) as fin: + lines = fin.readlines() + lines[0] = 'var NGROK_URL = "{}"\n'.format(socket_url.replace('http', 'ws')) + + with open(os.path.join(temp_dir, BASE_JS_FILE), 'w') as fout: + for line in lines: + fout.write(line) + + +def set_socket_port_in_js(temp_dir, socket_port): + with open(os.path.join(temp_dir, BASE_JS_FILE)) as fin: + lines = fin.readlines() + lines[1] = 'var SOCKET_PORT = {}\n'.format(socket_port) + + with open(os.path.join(temp_dir, BASE_JS_FILE), 'w') as fout: + for line in lines: + fout.write(line) + + +def get_first_available_port(initial, final): + """ + Gets the first open port in a specified range of port numbers + :param initial: the initial value in the range of port numbers + :param final: final (exclusive) value in the range of port numbers, should be greater than `initial` + :return: + """ + for port in range(initial, final): try: s = socket.socket() # create a socket object s.bind((LOCALHOST_NAME, port)) # Bind to the port s.close() + return port except OSError: - ports_in_use.append(port) - return ports_in_use - # ports_in_use = [] - # try: - # for proc in process_iter(): - # for conns in proc.connections(kind='inet'): - # ports_in_use.append(conns.laddr.port) - # except AccessDenied: - # pass # TODO(abidlabs): somehow find a way to handle this issue? - # return ports_in_use + pass + raise OSError("All ports from {} to {} are in use. Please close a port.".format(initial, final)) def serve_files_in_background(port, directory_to_serve=None): - # class Handler(http.server.SimpleHTTPRequestHandler): - # def __init__(self, *args, **kwargs): - # super().__init__(*args, directory=directory_to_serve, **kwargs) - # - # server = socketserver.ThreadingTCPServer(('localhost', port), Handler) - # # Ensures that Ctrl-C cleanly kills all spawned threads - # server.daemon_threads = True - # # Quicker rebinding - # server.allow_reuse_address = True - # - # # A custom signal handle to allow us to Ctrl-C out of the process - # def signal_handler(signal, frame): - # print('Exiting http server (Ctrl+C pressed)') - # try: - # if (server): - # server.server_close() - # finally: - # sys.exit(0) - # - # # Install the keyboard interrupt handler - # signal.signal(signal.SIGINT, signal_handler) class HTTPHandler(SimpleHTTPRequestHandler): """This handler uses server.base_path instead of always using os.getcwd()""" @@ -101,21 +150,9 @@ def serve_files_in_background(port, directory_to_serve=None): def start_simple_server(directory_to_serve=None): - # TODO(abidlabs): increment port number until free port is found - ports_in_use = get_ports_in_use(start=INITIAL_PORT_VALUE, stop=INITIAL_PORT_VALUE + TRY_NUM_PORTS) - for i in range(TRY_NUM_PORTS): - if not((INITIAL_PORT_VALUE + i) in ports_in_use): - break - else: - raise OSError("All ports from {} to {} are in use. Please close a port.".format( - INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS)) - serve_files_in_background(INITIAL_PORT_VALUE + i, directory_to_serve) - # if directory_to_serve is None: - # subprocess.Popen(['python', '-m', 'http.server', str(INITIAL_PORT_VALUE + i)]) - # else: - # cmd = ' '.join(['python', '-m', 'http.server', '-d', directory_to_serve, str(INITIAL_PORT_VALUE + i)]) - # subprocess.Popen(cmd, shell=True) # Doesn't seem to work if list is passed for some reason. - return INITIAL_PORT_VALUE + i + port = get_first_available_port(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS) + serve_files_in_background(port, directory_to_serve) + return port def download_ngrok(): @@ -133,7 +170,7 @@ def download_ngrok(): os.chmod('ngrok', st.st_mode | stat.S_IEXEC) -def setup_ngrok(local_port, api_url=NGROK_TUNNELS_API_URL): +def create_ngrok_tunnel(local_port, api_url): if not(os.path.isfile('ngrok.exe') or os.path.isfile('ngrok')): download_ngrok() if sys.platform == 'win32': @@ -147,18 +184,26 @@ def setup_ngrok(local_port, api_url=NGROK_TUNNELS_API_URL): session.mount('https://', adapter) r = session.get(api_url) for tunnel in r.json()['tunnels']: - if LOCALHOST_PREFIX + str(local_port) in tunnel['config']['addr']: + if '{}:'.format(LOCALHOST_NAME) + str(local_port) in tunnel['config']['addr']: return tunnel['public_url'] raise RuntimeError("Not able to retrieve ngrok public URL") -def kill_processes(process_ids): +def setup_ngrok(server_port, websocket_port, output_directory): + kill_processes([4040, 4041]) #TODO(abidlabs): better way to do this + site_ngrok_url = create_ngrok_tunnel(server_port, NGROK_TUNNELS_API_URL) + socket_ngrok_url = create_ngrok_tunnel(websocket_port, NGROK_TUNNELS_API_URL2) + set_socket_url_in_js(output_directory, socket_ngrok_url) + return site_ngrok_url + + +def kill_processes(process_ids): #TODO(abidlabs): remove this, we shouldn't need to kill for proc in process_iter(): try: for conns in proc.connections(kind='inet'): if conns.laddr.port in process_ids: proc.send_signal(SIGTERM) # or SIGKILL - except AccessDenied: + except (AccessDenied, NoSuchProcess): pass diff --git a/build/lib/gradio/outputs.py b/build/lib/gradio/outputs.py index 9a0e5b6fc0..3223ffb1a5 100644 --- a/build/lib/gradio/outputs.py +++ b/build/lib/gradio/outputs.py @@ -1,5 +1,13 @@ +""" +This module defines various classes that can serve as the `output` to an interface. Each class must inherit from +`AbstractOutput`, and each class must define a path to its template. All of the subclasses of `AbstractOutput` are +automatically added to a registry, which allows them to be easily referenced in other parts of the code. +""" + from abc import ABC, abstractmethod import numpy as np +import json +from gradio import imagenet_class_labels class AbstractOutput(ABC): """ @@ -9,52 +17,86 @@ class AbstractOutput(ABC): def __init__(self, postprocessing_fn=None): """ + :param postprocessing_fn: an optional postprocessing function that overrides the default """ if postprocessing_fn is not None: - self._post_process = postprocessing_fn + self.postprocess = postprocessing_fn super().__init__() @abstractmethod - def _get_template_path(self): + def get_template_path(self): """ All interfaces should define a method that returns the path to its template. """ pass @abstractmethod - def _post_process(self): + def postprocess(self, prediction): """ - All interfaces should define a method that returns the path to its template. + All interfaces should define a default postprocessing method """ pass -class Class(AbstractOutput): +class Label(AbstractOutput): + LABEL_KEY = 'label' + CONFIDENCES_KEY = 'confidences' + CONFIDENCE_KEY = 'confidence' - def _get_template_path(self): - return 'templates/class_output.html' + def __init__(self, postprocessing_fn=None, num_top_classes=3, show_confidences=True, label_names=None, + max_label_length=None): + self.num_top_classes = num_top_classes + self.show_confidences = show_confidences + self.label_names = label_names + self.max_label_length = max_label_length + super().__init__(postprocessing_fn=postprocessing_fn) - def _post_process(self, prediction): + def get_label_name(self, label): + if self.label_names is None: + name = label + elif self.label_names == 'imagenet1000': + name = imagenet_class_labels.NAMES1000[label] + else: # if list or dictionary + name = self.label_names[label] + if self.max_label_length is not None: + name = name[:self.max_label_length] + return name + + def get_template_path(self): + return 'templates/label_output.html' + + def postprocess(self, prediction): """ """ + response = dict() + # TODO(abidlabs): check if list, if so convert to numpy array if isinstance(prediction, np.ndarray): prediction = prediction.squeeze() - if prediction.size == 1: - return prediction - else: - return prediction.argmax() + if prediction.size == 1: # if it's single value + response[Label.LABEL_KEY] = self.get_label_name(np.asscalar(prediction)) + elif len(prediction.shape) == 1: # if a 1D + response[Label.LABEL_KEY] = self.get_label_name(int(prediction.argmax())) + if self.show_confidences: + response[Label.CONFIDENCES_KEY] = [] + for i in range(self.num_top_classes): + response[Label.CONFIDENCES_KEY].append({ + Label.LABEL_KEY: self.get_label_name(int(prediction.argmax())), + Label.CONFIDENCE_KEY: float(prediction.max()), + }) + prediction[prediction.argmax()] = 0 elif isinstance(prediction, str): - return prediction + response[Label.LABEL_KEY] = prediction else: raise ValueError("Unable to post-process model prediction.") + return json.dumps(response) class Textbox(AbstractOutput): - def _get_template_path(self): + def get_template_path(self): return 'templates/textbox_output.html' - def _post_process(self, prediction): + def postprocess(self, prediction): """ """ return prediction diff --git a/build/lib/gradio/templates/base_template.html b/build/lib/gradio/templates/base_template.html new file mode 100644 index 0000000000..a8e29e925f --- /dev/null +++ b/build/lib/gradio/templates/base_template.html @@ -0,0 +1,28 @@ + + + + Gradio + + + + + + + + + + +
+
+
+ +
+
+
+
+
+ + diff --git a/build/lib/gradio/templates/image_upload_input.html b/build/lib/gradio/templates/image_upload_input.html index f6a2f33b97..ee02413ecb 100644 --- a/build/lib/gradio/templates/image_upload_input.html +++ b/build/lib/gradio/templates/image_upload_input.html @@ -1,31 +1,11 @@ - -
-
Image Upload Input:
- -
-
Click here
or
drag and drop
an image - - -
-
- - -
- - -
- + + + diff --git a/build/lib/gradio/templates/label_output.html b/build/lib/gradio/templates/label_output.html new file mode 100644 index 0000000000..f9303439eb --- /dev/null +++ b/build/lib/gradio/templates/label_output.html @@ -0,0 +1,7 @@ +
+
Output
+
+
+
+
+ diff --git a/dist/gradio-0.2.1-py3-none-any.whl b/dist/gradio-0.3.1-py3-none-any.whl similarity index 95% rename from dist/gradio-0.2.1-py3-none-any.whl rename to dist/gradio-0.3.1-py3-none-any.whl index 1bf896e7983760222fb36775d684acb9a4884ec3..fcd096178ed4f16c4c67cd4c522535df24d38e70 100644 GIT binary patch delta 27642 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 delta 10987 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 { // $(".output_class").text(event.data); var data = JSON.parse(event.data) - data = { - label: "happy", - confidences : [ - { - label : "happy", - confidence: 0.7 - }, - { - label : "sad", - confidence: 0.3 - }, - ] - } + // data = { + // label: "happy", + // confidences : [ + // { + // label : "happy", + // confidence: 0.7 + // }, + // { + // label : "sad", + // confidence: 0.3 + // }, + // ] + // } $(".output_class").text(data["label"]) $(".confidence_intervals").empty() if ("confidences" in data) { diff --git a/gradio/static/js/image-upload-input.js b/gradio/static/js/image-upload-input.js index 6dec0cdc98..cf9986f015 100644 --- a/gradio/static/js/image-upload-input.js +++ b/gradio/static/js/image-upload-input.js @@ -1,4 +1,4 @@ -var cropper; +// var cropper; $('body').on('click', ".input_image.drop_mode", function (e) { $(this).parent().find(".hidden_upload").click(); @@ -17,10 +17,10 @@ function loadPreviewFromFiles(files) { $(".input_image").removeClass("drop_mode") var image = $(".input_image img") image.attr("src", this.result) - image.cropper({aspectRatio : 1.0}); - if (!cropper) { - cropper = image.data('cropper'); - } + // image.cropper({aspectRatio : 1.0}); + // if (!cropper) { + // cropper = image.data('cropper'); + // } } } @@ -50,10 +50,10 @@ $('body').on('click', '.submit', function(e) { }) $('body').on('click', '.clear', function(e) { - if (cropper) { - cropper.destroy(); - cropper = null - } + // if (cropper) { + // cropper.destroy(); + // cropper = null + // } $(".input_caption").show() $(".input_image img").removeAttr("src"); $(".input_image").addClass("drop_mode") diff --git a/setup.py b/setup.py index 9b55184831..c9ef587a2a 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ except ImportError: setup( name='gradio', - version='0.2.1', + version='0.3.1', include_package_data=True, description='Python library for easily interacting with trained machine learning models', author='Abubakar Abid',