commit 0ee4301a8c30a68847ba4118fa2822198971632c Author: poni Date: Mon Dec 12 14:33:46 2022 +0100 first commit diff --git a/_pics.ipynb b/_pics.ipynb new file mode 100644 index 0000000..5efd9df --- /dev/null +++ b/_pics.ipynb @@ -0,0 +1,413 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "bbf97edb-4082-49fd-9946-56aa3f3d0eb4", + "metadata": {}, + "outputs": [], + "source": [ + "import selenium \n", + "from selenium import webdriver\n", + "from selenium.webdriver.common.by import By\n", + "import time\n", + "import requests\n", + "import os\n", + "import io\n", + "import json\n", + "import random\n", + "import json\n", + "\n", + "DRIVER_PATH = './geckodriver'\n", + "DRIVER_PATH2 = './chromedriver'" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "d53ab4b1-da92-4ae2-ae11-02fa2d8ffe7c", + "metadata": {}, + "outputs": [], + "source": [ + " def harvesting(query:str, max_links_to_fetch:int, wd:webdriver, sleep_between_interactions:int=1):\n", + " dictionary = open('pics.json',)\n", + " l = json.load(dictionary)\n", + " \n", + " cycles = 3\n", + "\n", + " def scroll_to_end(wd):\n", + " wd.execute_script(\"window.scrollTo(0, document.body.scrollHeight);\")\n", + " time.sleep(sleep_between_interactions) \n", + " \n", + " # build the google query\n", + " search_url = \"https://www.google.com/search?safe=off&site=&tbm=isch&source=hp&q={q}&oq={q}&gs_l=img\"\n", + "\n", + " # load the page\n", + " wd.get(search_url.format(q=query))\n", + "\n", + " image_urls = set()\n", + " image_count = 0\n", + " results_start = 0\n", + " \n", + " sx =\"sx\"\n", + " dx=\"dx\"\n", + "\n", + " \n", + " while image_count < max_links_to_fetch:\n", + " for loop in range(cycles):\n", + " scroll_to_end(wd)\n", + " time.sleep(.1)\n", + "\n", + " # get all image thumbnail results\n", + " thumbnail_results = wd.find_elements(By.CLASS_NAME,\"Q4LuWd\")\n", + " number_results = len(thumbnail_results)\n", + " print(f\"Found: {number_results} search results. Extracting links from {results_start}:{number_results}\")\n", + " \n", + " # some useful variables\n", + " nPic = 0\n", + " holdPic=0\n", + " groundPic = 0\n", + " currentMeta = ''\n", + "\n", + " \n", + " for img in thumbnail_results[results_start:number_results]:\n", + " # click the thumbnail to get the actual image\n", + " try:\n", + " img.click()\n", + " time.sleep(.1)\n", + " except Exception:\n", + " continue\n", + "\n", + " # extract image url\n", + " actual_images = wd.find_elements(By.CLASS_NAME,'n3VNCb')\n", + " actual_image = actual_images[-1]\n", + " if actual_image.get_attribute('src') and 'http' in actual_image.get_attribute('src'):\n", + " image_urls.add(actual_image.get_attribute('src'))\n", + " linkPic = actual_image.get_attribute('src')\n", + " #\n", + " # print(linkPic)\n", + " \n", + " l[nPic] = linkPic\n", + " time.sleep(.5)\n", + "\n", + " # print(l) \n", + "\n", + " \n", + " with open(\"_harvesting/pics.json\", \"w\") as outfile: \n", + " json.dump(l, outfile) \n", + " \n", + " nPic = nPic+1\n", + "\n", + " holdPic = holdPic+1\n", + " time.sleep(.5)\n", + "\n", + " image_count = len(image_urls)\n", + "\n", + " if len(image_urls) >= max_links_to_fetch:\n", + " print(f\"Found: {len(image_urls)} image links, done!\")\n", + " break\n", + " else:\n", + " print(\"Found:\", len(image_urls), \"image links, looking for more ...\")\n", + " time.sleep(1)\n", + " return\n", + " load_more_button = wd.find_element(By.CLASS_NAME,\"Mye4qd\")\n", + " if load_more_button:\n", + " wd.execute_script(\"document.querySelector('.mye4qd').click();\")\n", + "\n", + " # move the result startpoint further down\n", + " results_start = len(thumbnail_results)\n", + "\n", + " return image_urls" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6de53389-ded8-47e2-b0aa-c132405a308f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/ipykernel_1545/1631965729.py:2: DeprecationWarning: executable_path has been deprecated, please pass in a Service object\n", + " wd = webdriver.Firefox(executable_path=DRIVER_PATH)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found: 289 search results. Extracting links from 0:289\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU', 76: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU', 76: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU', 77: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU', 76: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU', 77: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU', 78: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRR_4FBqcyRhFQpTZTKcEznIDpiQ2N142gYCw&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU', 76: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU', 77: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU', 78: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU', 79: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRR_4FBqcyRhFQpTZTKcEznIDpiQ2N142gYCw&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFOEvd24vMX707sqWK91s2rZuMPUAdS62Pr7M73gphp2o7BKZtGKvlIP_kkzwDELP9zGE&usqp=CAU\n", + "{0: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU', 1: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU', 2: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU', 3: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU', 4: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU', 5: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU', 6: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU', 7: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU', 8: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU', 9: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU', 10: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU', 11: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU', 12: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU', 13: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU', 14: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU', 15: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU', 16: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU', 17: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU', 18: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU', 19: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU', 20: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU', 21: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU', 22: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU', 23: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU', 24: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU', 25: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU', 26: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU', 27: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU', 28: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU', 29: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU', 30: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU', 31: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU', 32: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU', 33: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU', 34: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU', 35: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU', 36: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU', 37: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU', 38: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU', 39: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU', 40: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU', 41: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU', 42: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU', 43: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU', 44: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU', 45: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU', 46: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU', 47: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU', 48: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU', 49: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU', 50: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU', 51: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU', 52: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU', 53: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU', 54: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU', 55: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU', 56: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU', 57: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU', 58: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU', 59: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU', 60: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU', 61: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU', 62: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU', 63: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU', 64: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU', 65: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU', 66: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU', 67: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU', 68: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU', 69: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU', 70: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU', 71: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU', 72: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU', 73: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU', 74: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU', 75: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU', 76: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU', 77: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU', 78: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU', 79: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRR_4FBqcyRhFQpTZTKcEznIDpiQ2N142gYCw&usqp=CAU', 80: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFOEvd24vMX707sqWK91s2rZuMPUAdS62Pr7M73gphp2o7BKZtGKvlIP_kkzwDELP9zGE&usqp=CAU'}\n", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU\n" + ] + } + ], + "source": [ + "if __name__ == '__main__':\n", + " wd = webdriver.Firefox(executable_path=DRIVER_PATH)\n", + " query = \"VAAST COLSON\"\n", + " wd.get('https://google.com')\n", + " time.sleep(1)\n", + " wd.find_element(By.ID,'W0wltc').click()\n", + "\n", + " time.sleep(.5)\n", + " \n", + " search_box = wd.find_element(By.CLASS_NAME,'gLFyf')\n", + " search_box.send_keys(query)\n", + " \n", + " links = harvesting(query,200,wd)\n", + " \n", + " wd.quit()" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "id": "e2f2b34f-ab75-41d4-82ff-e69b8c0c4481", + "metadata": {}, + "outputs": [], + "source": [ + " #if (nPic%2):\n", + " # wd2.execute_script(f\"document.querySelector('.scene3D').innerHTML += '
'\")\n", + " # else:\n", + " # wd2.execute_script(f\"document.querySelector('.scene3D').innerHTML += '
'\")\n", + " #if (holdPic == 50):\n", + " # for rPic in range(groundPic,groundPic+10):\n", + " # try:\n", + " # wd2.execute_script(f\"remove('pic{rPic}')\")\n", + " # except:\n", + " # print('eheh')\n", + " # groundPic = groundPic+10\n", + " # holdPic = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "ba2a67d3-8958-48eb-8f98-7d7d97d61706", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\n", + "Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.\n", + "Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\n", + "Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.\n", + "Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.\n", + "Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.\n", + "Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\n", + "MOSTRE ED EVENTI CHE RIGUARDANO Vaast Colson. TUTTIIN CORSOCONCLUSIFUTURI. Sanguine. Luc Tuymans on Baroque. Dal 17 ottobre 2018 al 25 febbraio 2019\n", + "Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.\n", + "Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\n" + ] + } + ], + "source": [ + "import json \n", + "dictionary = open('_harvesting/meta.json',)\n", + "l = json.load(dictionary)\n", + "for x in range(10):\n", + " print(l[str(x)])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5d60578-9ce2-491b-be89-4a4dc3cc1203", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/_text.ipynb b/_text.ipynb new file mode 100644 index 0000000..22cb64d --- /dev/null +++ b/_text.ipynb @@ -0,0 +1,221 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "id": "15d4a3da-ea42-4559-a007-24ce9726ebd9", + "metadata": {}, + "outputs": [], + "source": [ + "import selenium \n", + "from selenium import webdriver\n", + "from selenium.webdriver.common.by import By\n", + "import time\n", + "import requests\n", + "import os\n", + "import io\n", + "import multiprocessing\n", + "import json\n", + "\n", + "DRIVER_PATH = './geckodriver'\n", + "DRIVER_PATH2 = './chromedriver'\n", + "\n", + "def meta(queries,wd3):\n", + " url = 'https://www.google.it/search?q=vaast+colson&sxsrf=ALiCzsYcMyMvNo67pjpN-zRgfmTXw1L6Zw%3A1670252242664&source=hp&ei=0gaOY7zUJfbjxc8Pu_2QmAE&iflsig=AJiK0e8AAAAAY44U4oHBLhsJUz-SOp-oMy5eO2PMIDLU&gs_ssp=eJzj4tVP1zc0TDKvMDJMqjQzYPTiKUtMLC5RSM7PKc7PAwB8eAkY&oq=vaast+colsan&gs_lcp=Cgdnd3Mtd2l6EAEYADIHCC4QgAQQDTIGCAAQHhANMgYIABAeEA0yBggAEB4QDTIGCAAQHhANMggIABAIEB4QDToECCMQJzoLCC4QgAQQxwEQ0QM6CAguENQCEIAEOggILhCABBDUAjoFCAAQgAQ6BQguEIAEOgsILhCABBDHARCvAToOCC4QgAQQxwEQ0QMQ1AI6CAguEIAEEMsBOggIABCABBDLAToLCC4Q1AIQgAQQywE6DgguEK8BEMcBEIAEEMsBOgoIABCABBAKEMsBOgcIABCABBAKOgYIABAWEB46CAgAEBYQHhAKOgUIABCGA1AAWMkOYK0XaAFwAHgBgAHhAogB-RKSAQcxLjYuNS4xmAEAoAEB&sclient=gws-wiz'\n", + " wd3.get(url)\n", + " wd3.find_element(By.ID,'W0wltc').click()\n", + " \n", + " dictionary = open('_harvesting/meta.json',)\n", + " l = json.load(dictionary)\n", + "\n", + " print(l)\n", + " print('jsonjson!')\n", + " \n", + " i=2\n", + " n = 0\n", + " \n", + " while True:\n", + " try: \n", + " wd3.find_element(By.CSS_SELECTOR, \"a[aria-label='Page {}']\".format(i)).click()\n", + " searchResults = wd3.find_elements(By.CLASS_NAME, 'VwiC3b')\n", + "\n", + "\n", + " for result in searchResults:\n", + " #l = ''\n", + " l[n] = result.text\n", + " time.sleep(.5)\n", + "\n", + " print(l) \n", + "\n", + " n=n+1\n", + " with open(\"_harvesting/meta.json\", \"w\") as outfile: \n", + " json.dump(l, outfile) \n", + "\n", + " time.sleep(.5)\n", + "\n", + " #wd2.execute_script(f\"document.querySelector('#text').innerHTML += {result.text}\")\n", + " print(\"Navigating to Next Page \" + str(i))\n", + " i=i+1\n", + " time.sleep(1)\n", + " except:\n", + " print(\"Last page reached\")\n", + " break\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "dc1b89a4-651c-4d71-8fcc-74fe170a4a7f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/ipykernel_1553/1235349729.py:2: DeprecationWarning: executable_path has been deprecated, please pass in a Service object\n", + " wd3 = webdriver.Chrome(executable_path=DRIVER_PATH2)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{}\n", + "jsonjson!\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...'}\n", + "Navigating to Next Page 2\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\"}\n", + "Navigating to Next Page 3\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.'}\n", + "Navigating to Next Page 4\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.'}\n", + "Navigating to Next Page 5\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...'}\n", + "Navigating to Next Page 6\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...'}\n", + "Navigating to Next Page 7\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].'}\n", + "Navigating to Next Page 8\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...'}\n", + "Navigating to Next Page 9\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\"}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...', 82: 'Vaast Colson. Artista. Nació en 1977 en Kapellen, Antwerpen, Bélgica. Reside en Bélgica.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...', 82: 'Vaast Colson. Artista. Nació en 1977 en Kapellen, Antwerpen, Bélgica. Reside en Bélgica.', 83: 'Apr 3, 2018 — Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...', 82: 'Vaast Colson. Artista. Nació en 1977 en Kapellen, Antwerpen, Bélgica. Reside en Bélgica.', 83: 'Apr 3, 2018 — Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...', 84: 'Colson, Vaast. Author(s): Title: Publication year: Publication place: Publisher: Edition: Pages: Dimensions: Binding: Specifications:'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...', 82: 'Vaast Colson. Artista. Nació en 1977 en Kapellen, Antwerpen, Bélgica. Reside en Bélgica.', 83: 'Apr 3, 2018 — Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...', 84: 'Colson, Vaast. Author(s): Title: Publication year: Publication place: Publisher: Edition: Pages: Dimensions: Binding: Specifications:', 85: 'Vaast Colson runs his own fan club from the castle as a true modern- day knight. Pictured is Fabian. Mérelle\\'s \"Chevalier\". Other works from the collection.'}\n", + "{0: \"View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...\", 1: 'Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.', 2: 'Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis — Antwerp. 10 September — 6 November 2005. Exhibition.', 3: \"Vaast Colson (°1977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...\", 4: 'Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.', 5: 'Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.', 6: \"Vaast Colson and Kati Heck “Show me yours & I'll show you mine” at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2′. Share.\", 7: 'Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.', 8: 'The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...', 9: \"Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...\", 10: \"'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...\", 11: 'vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...', 12: \"Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque · ATP DIARY · 2 Minutes · Talks · Art Text · Artist's Diary · Colophon · Contact ...\", 13: 'About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...', 14: 'Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...', 15: 'Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.', 16: 'Vaast Colson: · \"N 50°53\\'41,47”– E 4°20\\'29,48”\" · \"You used to be part of something (public poster edition)\" · \"SIZING & RESIZING - All sound intentions and then ...', 17: 'w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...', 18: \"Kunsthuis Yellowart - curator Vaast Colson. “Ik stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...\", 19: 'Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.', 20: 'Vaast Colson. Webring. Arte.Go.it · Arte.Go.Shop · dgPixel Multimedia · TechShop · TechBlog · Redazione Cultura · WordPress Area Test', 21: 'Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Audéoud, Vaast Colson, ...', 22: \"Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...\", 23: \"Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...\", 24: 'Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.', 25: '35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: “Vaast Colson #muhka #vaastcolson #antwerp”', 26: 'artist, Figure 87: Vaast Colson. term, eternal network / la fête permanente. year, 2016. courtesy of, Courtesy of the artist © M HKA.', 27: 'Vaast Colson. Save. Cancel. Delete. Events · Edit · Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam · The Image Generator. 29 Jan - 01 Feb 2015.', 28: 'Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...', 29: \"... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.\", 30: '27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.', 31: 'Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions · Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.', 32: 'In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...', 33: 'Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...', 34: 'Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,', 35: 'Apr 13, 2022 — Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...', 36: 'AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.', 37: 'Marc Nagtzaam · Fabienne Audéoud · Christine Meisner · Vaast Colson · Mekhitar Garabedian · Raymond Pettibon · Javier Téllez · Abraham Cruzvillegas.', 38: \"IAC — Institut d'art contemporain — Villeurbanne/Rhône-Alpes.\", 39: \"Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...\", 40: \"Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.\", 41: 'Oct 4, 2021 — Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.', 42: 'Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...', 43: 'een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, … a frank conversation with Vaast ...', 44: 'Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.', 45: 'Vaast Colson · Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. · Schrijf ...', 46: 'FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.', 47: 'Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...', 48: \"Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.\", 49: \"Apr 19, 2009 — In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...\", 50: 'In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...', 51: 'Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...', 52: 'Oct 7, 2020 — Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...', 53: 'Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...', 54: 'In 2001 galoppeerde Vaast Colson (°1977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...', 55: 'Vaast Colson. museum notebook. Hardcover | Nederlands. € 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.', 56: '[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...', 57: 'Vaast Colson. Schwarzer Peter — das Original. 20.12.2019 — 21.12.2019. Presentatie van de editie: VAAST COLSON, “ ...', 58: 'May 15, 2015 — Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...', 59: \"Aug 25, 2013 — Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving – the synthesis of the 12 portraits – at which you can sit to make ...\", 60: 'Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.', 61: \"Consultez les coordonnées, dirigeants et chiffres-clés de VAAST COLSON FOUNDATION (0892.660.019) à Antwerpen (2018) et d'autres sociétés du secteur Art, ...\", 62: \"Recyclart et JAP s'associent une fois de plus, à Chapelle cette fois, et présentent ensemble une exposition de l'artiste Vaast Colson.\", 63: 'Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR®) are reserved by the ...', 64: 'Drop by on 3 December for an artist talk with Vaast Colson. With works by Aurélie Bayad – Oona Bovri – Vaast Colson – Marijke De Roover – Messieurs Delmotte – ...', 65: 'Oct 20, 2019 — Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...', 66: 'PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...', 67: 'Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].', 68: 'Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material – on artist. Maes & Matthys Gallery, 2009.', 69: 'VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.', 70: 'CIAP is een centrum voor actuele kunst gevestigd in Hasselt, België.', 71: 'Sep 12, 2022 — Bid now on Invaluable: VAAST COLSON (°1977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.', 72: 'Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).', 73: '2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...', 74: 'Jun 27, 2015 — Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.', 75: 'Mar 24, 2012 — Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...', 76: \"Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...\", 77: 'Jun 27, 2015 — Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...', 78: 'Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...', 79: \"Feb 27, 2016 — Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...\", 80: 'Sep 24, 2009 — Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.', 81: 'Vaast Colson. Agenda · 20 jaar Ultra Eczema · SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...', 82: 'Vaast Colson. Artista. Nació en 1977 en Kapellen, Antwerpen, Bélgica. Reside en Bélgica.', 83: 'Apr 3, 2018 — Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...', 84: 'Colson, Vaast. Author(s): Title: Publication year: Publication place: Publisher: Edition: Pages: Dimensions: Binding: Specifications:', 85: 'Vaast Colson runs his own fan club from the castle as a true modern- day knight. Pictured is Fabian. Mérelle\\'s \"Chevalier\". Other works from the collection.', 86: 'Feb 19, 2016 — Vaast Colson (Kapellen, 1977 – woont en werkt in Antwerpen) staat bekend om zijn veelzijdig beeldend werk dat sculpturen, installaties, ...'}\n", + "Last page reached\n" + ] + } + ], + "source": [ + "if __name__ == '__main__':\n", + " wd3 = webdriver.Chrome(executable_path=DRIVER_PATH2)\n", + " queries = [\"VAAST COLSON\"]\n", + " meta(queries,wd3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff6d1cee-8462-4692-b5b6-d14a1960bd1b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/axios-example/.gitattributes b/axios-example/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/axios-example/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/axios-example/.gitignore b/axios-example/.gitignore new file mode 100644 index 0000000..9a52d6f --- /dev/null +++ b/axios-example/.gitignore @@ -0,0 +1,2 @@ +*.pyc +/.venv/* \ No newline at end of file diff --git a/axios-example/app.py b/axios-example/app.py new file mode 100644 index 0000000..2385c8f --- /dev/null +++ b/axios-example/app.py @@ -0,0 +1,39 @@ +from flask import Flask, render_template, jsonify +import random +from datetime import datetime +import json +import os + +app = Flask('app') + +# dir_path = os.path.dirname(os.path.realpath(__file__)) +# pics_file_path = os.path.join(dir_path,'pics.py') +# metatext_file_path = os.path.join(dir_path,'meta.py') +# os.system(f'python3 {pics_file_path}') +# os.system(f'python3 {metatext_file_path}') + +@app.route('/') + +def index(): + return render_template('index.html') + +@app.route('/api/datapoint') + +def api_datapoint(): + + metaDict = open('meta.json',) + meta = json.load(metaDict) + + picsDict = open('pics.json',) + pics = json.load(picsDict) + + + dictionary_to_return = { + 'meta': meta, + 'pics': pics + } + + return jsonify(dictionary_to_return) + + +app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/axios-example/bin/Activate.ps1 b/axios-example/bin/Activate.ps1 new file mode 100644 index 0000000..eeea358 --- /dev/null +++ b/axios-example/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/axios-example/bin/activate b/axios-example/bin/activate new file mode 100644 index 0000000..53ec58b --- /dev/null +++ b/axios-example/bin/activate @@ -0,0 +1,69 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/Users/poni/_harvesting/axios-example" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(axios-example) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(axios-example) " + export VIRTUAL_ENV_PROMPT +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/axios-example/bin/activate.csh b/axios-example/bin/activate.csh new file mode 100644 index 0000000..8f053f7 --- /dev/null +++ b/axios-example/bin/activate.csh @@ -0,0 +1,26 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/poni/_harvesting/axios-example" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(axios-example) $prompt" + setenv VIRTUAL_ENV_PROMPT "(axios-example) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/axios-example/bin/activate.fish b/axios-example/bin/activate.fish new file mode 100644 index 0000000..073884d --- /dev/null +++ b/axios-example/bin/activate.fish @@ -0,0 +1,66 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/); you cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + functions -e fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/poni/_harvesting/axios-example" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(axios-example) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(axios-example) " +end diff --git a/axios-example/bin/flask b/axios-example/bin/flask new file mode 100755 index 0000000..905414a --- /dev/null +++ b/axios-example/bin/flask @@ -0,0 +1,8 @@ +#!/Users/poni/_harvesting/axios-example/bin/python3.10 +# -*- coding: utf-8 -*- +import re +import sys +from flask.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/axios-example/bin/normalizer b/axios-example/bin/normalizer new file mode 100755 index 0000000..1f0b7f7 --- /dev/null +++ b/axios-example/bin/normalizer @@ -0,0 +1,8 @@ +#!/Users/poni/_harvesting/axios-example/bin/python3.10 +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli.normalizer import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/axios-example/bin/pip b/axios-example/bin/pip new file mode 100755 index 0000000..bb7b4c7 --- /dev/null +++ b/axios-example/bin/pip @@ -0,0 +1,8 @@ +#!/Users/poni/_harvesting/axios-example/bin/python3.10 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/axios-example/bin/pip3 b/axios-example/bin/pip3 new file mode 100755 index 0000000..bb7b4c7 --- /dev/null +++ b/axios-example/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/poni/_harvesting/axios-example/bin/python3.10 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/axios-example/bin/pip3.10 b/axios-example/bin/pip3.10 new file mode 100755 index 0000000..bb7b4c7 --- /dev/null +++ b/axios-example/bin/pip3.10 @@ -0,0 +1,8 @@ +#!/Users/poni/_harvesting/axios-example/bin/python3.10 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/axios-example/bin/python b/axios-example/bin/python new file mode 120000 index 0000000..c3cc991 --- /dev/null +++ b/axios-example/bin/python @@ -0,0 +1 @@ +python3.10 \ No newline at end of file diff --git a/axios-example/bin/python3 b/axios-example/bin/python3 new file mode 120000 index 0000000..c3cc991 --- /dev/null +++ b/axios-example/bin/python3 @@ -0,0 +1 @@ +python3.10 \ No newline at end of file diff --git a/axios-example/bin/python3.10 b/axios-example/bin/python3.10 new file mode 120000 index 0000000..ef50bb7 --- /dev/null +++ b/axios-example/bin/python3.10 @@ -0,0 +1 @@ +/usr/local/opt/python@3.10/bin/python3.10 \ No newline at end of file diff --git a/axios-example/geckodriver.log b/axios-example/geckodriver.log new file mode 100644 index 0000000..e8e530e --- /dev/null +++ b/axios-example/geckodriver.log @@ -0,0 +1,2117 @@ +1670538321079 geckodriver INFO Listening on 127.0.0.1:50039 +1670538321612 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50040" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileVR6sKX" +2022-12-08 23:25:22.672 plugin-container[1865:21856] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:22.673 plugin-container[1865:21856] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:25:22.677 plugin-container[1865:21856] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:22.677 plugin-container[1865:21856] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:25:22.678 plugin-container[1865:21861] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:22.679 plugin-container[1865:21861] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538322782 Marionette INFO Marionette enabled +1670538322815 Marionette INFO Listening on port 50048 +Read port: 50048 +WebDriver BiDi listening on ws://127.0.0.1:50040 +1670538323504 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileVR6sKX/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50040/devtools/browser/f80431f2-670e-465e-aa9c-5f7022c43729 +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +1670538330332 geckodriver INFO Listening on 127.0.0.1:50088 +1670538330846 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50089" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileCDnagm" +2022-12-08 23:25:31.546 plugin-container[1895:22379] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:31.547 plugin-container[1895:22379] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538331564 Marionette INFO Marionette enabled +2022-12-08 23:25:31.576 plugin-container[1895:22379] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:31.576 plugin-container[1895:22379] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:25:31.577 plugin-container[1895:22381] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:25:31.577 plugin-container[1895:22381] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538331933 Marionette INFO Listening on port 50096 +Read port: 50096 +WebDriver BiDi listening on ws://127.0.0.1:50089 +1670538332069 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileCDnagm/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50089/devtools/browser/d7520750-5e10-481f-a2e3-3070f2fa9f49 +Exiting due to channel error. +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +1670538652602 geckodriver INFO Listening on 127.0.0.1:50182 +1670538653118 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50183" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileTmrVrd" +2022-12-08 23:30:53.574 plugin-container[2095:25176] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:30:53.576 plugin-container[2095:25176] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:30:53.584 plugin-container[2095:25176] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:30:53.584 plugin-container[2095:25176] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:30:53.585 plugin-container[2095:25178] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:30:53.585 plugin-container[2095:25178] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538653707 Marionette INFO Marionette enabled +1670538653778 Marionette INFO Listening on port 50188 +Read port: 50188 +WebDriver BiDi listening on ws://127.0.0.1:50183 +1670538654322 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileTmrVrd/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50183/devtools/browser/0d98f12c-f234-4b25-a5ef-86780199d520 +Exiting due to channel error. +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +1670538709150 geckodriver INFO Listening on 127.0.0.1:50245 +1670538709669 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50246" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileHpAaIE" +2022-12-08 23:31:50.116 plugin-container[2154:26091] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:31:50.116 plugin-container[2154:26091] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:31:50.128 plugin-container[2154:26091] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:31:50.128 plugin-container[2154:26091] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:31:50.128 plugin-container[2154:26093] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:31:50.129 plugin-container[2154:26093] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538710366 Marionette INFO Marionette enabled +1670538710400 Marionette INFO Listening on port 50251 +Read port: 50251 +WebDriver BiDi listening on ws://127.0.0.1:50246 +1670538710739 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileHpAaIE/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50246/devtools/browser/78c7a46a-9ad5-4e1a-98cb-9b5974cbb1f0 +1670538759246 geckodriver INFO Listening on 127.0.0.1:50311 +1670538759258 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50312" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileC8x9Yg" +2022-12-08 23:32:39.920 plugin-container[2218:26937] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:32:39.921 plugin-container[2218:26937] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:32:39.927 plugin-container[2218:26937] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:32:39.927 plugin-container[2218:26937] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:32:39.928 plugin-container[2218:26935] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:32:39.928 plugin-container[2218:26935] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538760180 Marionette INFO Marionette enabled +1670538760238 Marionette INFO Listening on port 50315 +Read port: 50315 +WebDriver BiDi listening on ws://127.0.0.1:50312 +1670538760492 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileC8x9Yg/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50312/devtools/browser/2d6fbc9f-121b-44ea-aac0-e19e19d1efeb +Exiting due to channel error. +Exiting due to channel error. +Exiting due to channel error. +1670538784010 geckodriver INFO Listening on 127.0.0.1:50359 +1670538784020 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50360" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileZSaeKd" +2022-12-08 23:33:04.674 plugin-container[2267:27635] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:33:04.674 plugin-container[2267:27635] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538784772 Marionette INFO Marionette enabled +2022-12-08 23:33:04.774 plugin-container[2267:27635] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:33:04.774 plugin-container[2267:27635] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:33:04.775 plugin-container[2267:27636] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:33:04.775 plugin-container[2267:27636] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670538785051 Marionette INFO Listening on port 50363 +Read port: 50363 +WebDriver BiDi listening on ws://127.0.0.1:50360 +1670538785185 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileZSaeKd/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50360/devtools/browser/4093c151-3b10-454c-976c-46224fd297cb +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +1670538802986 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538803836 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538804673 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538805510 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538806346 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538807185 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538808048 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538808884 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538857483 geckodriver INFO Listening on 127.0.0.1:50492 +1670538857988 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50493" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileh1B3xv" +1670538858642 Marionette INFO Marionette enabled +1670538858679 Marionette INFO Listening on port 50498 +Read port: 50498 +2022-12-08 23:34:18.770 plugin-container[2332:28856] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:34:18.772 plugin-container[2332:28856] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:34:18.776 plugin-container[2332:28856] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:34:18.776 plugin-container[2332:28856] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:34:18.776 plugin-container[2332:28878] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:34:18.776 plugin-container[2332:28878] nil host used in call to allowsAnyHTTPSCertificateForHost: +WebDriver BiDi listening on ws://127.0.0.1:50493 +1670538859007 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileh1B3xv/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50493/devtools/browser/5fc63259-a6f1-41a5-b011-45c9c90ec7b8 +1670538864384 Marionette INFO Stopped listening on port 50251 +1670538868992 Marionette INFO Stopped listening on port 50363 +1670538920665 geckodriver INFO Listening on 127.0.0.1:50566 +1670538921178 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50567" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileEmdhjl" +1670538921877 Marionette INFO Marionette enabled +1670538921908 Marionette INFO Listening on port 50572 +2022-12-08 23:35:21.952 plugin-container[2397:29804] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:35:21.952 plugin-container[2397:29804] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:35:21.955 plugin-container[2397:29804] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:35:21.956 plugin-container[2397:29804] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-08 23:35:21.956 plugin-container[2397:29811] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-08 23:35:21.956 plugin-container[2397:29811] nil host used in call to allowsAnyHTTPSCertificateForHost: +Read port: 50572 +WebDriver BiDi listening on ws://127.0.0.1:50567 +1670538922290 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileEmdhjl/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50567/devtools/browser/171fcc4c-37e4-4f30-816f-b64e8d6b8602 +1670538932862 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538961641 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538963515 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538965390 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538967244 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538969107 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670538971045 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +console.error: (new TypeError("currentNode is null", "resource://devtools/client/inspector/shared/style-change-tracker.js", 66)) +TypeError: currentNode is null: canMutationImpactCurrentStyles@resource://devtools/client/inspector/shared/style-change-tracker.js:66:20 +onMutations@resource://devtools/client/inspector/shared/style-change-tracker.js:84:41 +_emit@resource://devtools/shared/event-emitter.js:242:32 +emit@resource://devtools/shared/event-emitter.js:186:18 +emit@resource://devtools/shared/event-emitter.js:330:18 +getMutations@resource://devtools/client/fronts/walker.js:313:10 + +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +1670539177905 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670539179774 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +console.error: (new TypeError("parent is null", "resource://devtools/client/inspector/shared/style-change-tracker.js", 67)) +TypeError: parent is null: canMutationImpactCurrentStyles@resource://devtools/client/inspector/shared/style-change-tracker.js:67:24 +onMutations@resource://devtools/client/inspector/shared/style-change-tracker.js:84:41 +_emit@resource://devtools/shared/event-emitter.js:242:32 +emit@resource://devtools/shared/event-emitter.js:186:18 +emit@resource://devtools/shared/event-emitter.js:330:18 +getMutations@resource://devtools/client/fronts/walker.js:313:10 + +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +console.error: (new TypeError("parent is null", "resource://devtools/client/inspector/shared/style-change-tracker.js", 67)) +TypeError: parent is null: canMutationImpactCurrentStyles@resource://devtools/client/inspector/shared/style-change-tracker.js:67:24 +onMutations@resource://devtools/client/inspector/shared/style-change-tracker.js:84:41 +_emit@resource://devtools/shared/event-emitter.js:242:32 +emit@resource://devtools/shared/event-emitter.js:186:18 +emit@resource://devtools/shared/event-emitter.js:330:18 +getMutations@resource://devtools/client/fronts/walker.js:313:10 + +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +Handler function threw an exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIHttpChannelInternal.remoteAddress]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: resource://devtools/server/actors/network-monitor/network-observer.js :: _onResponseHeader :: line 1004" data: no] +Stack: _onResponseHeader@resource://devtools/server/actors/network-monitor/network-observer.js:1004:5 +_dispatchActivity@resource://devtools/server/actors/network-monitor/network-observer.js:577:14 +NetworkObserver.prototype.observeActivity<@resource://devtools/server/actors/network-monitor/network-observer.js:686:12 +exports.makeInfallible/<@resource://devtools/shared/ThreadSafeDevToolsUtils.js:103:22 +Line: 1004, column: 0 +console.error: ({}) +Handler function threw an exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIHttpChannelInternal.remoteAddress]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: resource://devtools/server/actors/network-monitor/network-observer.js :: _onResponseHeader :: line 1004" data: no] +Stack: _onResponseHeader@resource://devtools/server/actors/network-monitor/network-observer.js:1004:5 +_dispatchActivity@resource://devtools/server/actors/network-monitor/network-observer.js:577:14 +NetworkObserver.prototype.observeActivity<@resource://devtools/server/actors/network-monitor/network-observer.js:686:12 +exports.makeInfallible/<@resource://devtools/shared/ThreadSafeDevToolsUtils.js:103:22 +Line: 1004, column: 0 +console.error: ({}) +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: http://127.0.0.1:5000/, line 122: ReferenceError: perspectiveOrigin is not defined +JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame' +JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame' +JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame' +JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame' +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +Exiting due to channel error. +Exiting due to channel error. +1670539323655 Marionette INFO Stopped listening on port 50498 +1670588968253 geckodriver INFO Listening on 127.0.0.1:52859 +1670588968824 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "52860" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileSgPa0l" +2022-12-09 13:29:30.471 plugin-container[4376:63025] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:29:30.471 plugin-container[4376:63025] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:29:30.479 plugin-container[4376:63025] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:29:30.479 plugin-container[4376:63025] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:29:30.480 plugin-container[4376:63040] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:29:30.480 plugin-container[4376:63040] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670588970508 Marionette INFO Marionette enabled +1670588970590 Marionette INFO Listening on port 52871 +Read port: 52871 +WebDriver BiDi listening on ws://127.0.0.1:52860 +1670588971266 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileSgPa0l/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:52860/devtools/browser/e413fc4c-0489-4c4c-82c3-eb16ccedd281 +1670588990327 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588991398 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588992392 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588993235 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588994108 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588994999 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588995856 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588996698 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588997541 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588998378 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670588999413 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589000509 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589001484 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589002377 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589003217 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589005080 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589007038 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589008925 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589010854 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589012745 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589014691 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589016569 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589018440 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589020323 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589022250 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589055284 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589057260 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589059155 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589360568 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589362592 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589364544 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589366736 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589368769 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589370749 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589372664 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589374551 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589376424 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589377789 Marionette INFO Stopped listening on port 52871 +1670589492761 geckodriver INFO Listening on 127.0.0.1:55743 +1670589492774 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "55744" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileg1BKCP" +2022-12-09 13:38:13.533 plugin-container[4861:69279] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:38:13.534 plugin-container[4861:69279] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:38:13.581 plugin-container[4861:69279] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:38:13.581 plugin-container[4861:69279] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:38:13.582 plugin-container[4861:69290] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:38:13.582 plugin-container[4861:69290] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670589493666 Marionette INFO Marionette enabled +1670589493758 Marionette INFO Listening on port 55755 +Read port: 55755 +WebDriver BiDi listening on ws://127.0.0.1:55744 +1670589494753 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileg1BKCP/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:55744/devtools/browser/7fd1c382-6038-4f60-ab79-56037ab9e57d +JavaScript error: , line 0: uncaught exception: Object +1670589521911 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589522763 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589523653 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589524524 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589525373 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589526257 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589527135 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589528036 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589529060 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589530522 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589531487 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589532495 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589533385 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589534266 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589535105 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589536973 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589538849 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589540728 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589542592 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589544764 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589550977 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589561311 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589563213 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589565081 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589566938 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589568791 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589570663 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589572532 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589574413 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589576281 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589578158 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589580053 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589581943 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589583904 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589585807 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589587695 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589589582 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589591459 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670589614241 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589616134 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589618002 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589619860 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589621747 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589623623 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589625489 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589627385 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589629267 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589631230 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589633111 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589635332 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589637202 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589639363 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589641610 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589643591 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589645472 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589647344 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589649226 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589651108 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589653022 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589654920 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589656790 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589658801 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589660686 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589662585 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589664465 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589677267 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589679202 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589681211 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589683299 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589685234 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589694315 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589699948 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589735696 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589737575 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589739514 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589741419 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589743423 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589745346 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589752194 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589755794 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589759377 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589761339 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589784396 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589786346 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +Exiting due to channel error. +1670589821686 geckodriver INFO Listening on 127.0.0.1:57506 +1670589822199 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "57507" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofilehdWGH1" +2022-12-09 13:43:42.799 plugin-container[5350:73690] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:43:42.799 plugin-container[5350:73690] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:43:42.806 plugin-container[5350:73690] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:43:42.806 plugin-container[5350:73690] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:43:42.807 plugin-container[5350:73692] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:43:42.807 plugin-container[5350:73692] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670589823132 Marionette INFO Marionette enabled +1670589823249 Marionette INFO Listening on port 57512 +Read port: 57512 +WebDriver BiDi listening on ws://127.0.0.1:57507 +1670589823857 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofilehdWGH1/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:57507/devtools/browser/2577098e-d9b3-4c00-bf23-608b89990865 +1670589828743 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589891045 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589921848 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670589923286 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670590016024 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670590148554 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670590160474 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670590177966 Marionette INFO Stopped listening on port 57512 +1670590211618 geckodriver INFO Listening on 127.0.0.1:60146 +1670590212134 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "60147" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofilebfcE4F" +1670590213011 Marionette INFO Marionette enabled +2022-12-09 13:50:13.114 plugin-container[5782:77847] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:50:13.114 plugin-container[5782:77847] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:50:13.119 plugin-container[5782:77847] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:50:13.119 plugin-container[5782:77847] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:50:13.120 plugin-container[5782:77874] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:50:13.120 plugin-container[5782:77874] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670590213181 Marionette INFO Listening on port 60152 +Read port: 60152 +WebDriver BiDi listening on ws://127.0.0.1:60147 +1670590213534 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofilebfcE4F/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:60147/devtools/browser/ec999729-07f2-4d0b-92db-1e934de365c7 +1670590263621 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670590443784 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670590459036 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670590460635 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +Exiting due to channel error. +1670590540581 geckodriver INFO Listening on 127.0.0.1:62549 +1670590540592 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "62550" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileLCseKj" +1670590542133 Marionette INFO Marionette enabled +1670590542212 Marionette INFO Listening on port 62565 +Read port: 62565 +2022-12-09 13:55:42.467 plugin-container[6133:82350] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:55:42.467 plugin-container[6133:82350] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:55:42.476 plugin-container[6133:82350] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:55:42.477 plugin-container[6133:82350] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:55:42.477 plugin-container[6133:82348] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:55:42.477 plugin-container[6133:82348] nil host used in call to allowsAnyHTTPSCertificateForHost: +Read port: 62565 +WebDriver BiDi listening on ws://127.0.0.1:62550 +1670590544220 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileLCseKj/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:62550/devtools/browser/6e6160d4-8bd9-46c4-b3de-a35066fcecfb +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +Exiting due to channel error. +1670590602236 geckodriver INFO Listening on 127.0.0.1:62724 +1670590602854 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "62725" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofiletGyVsy" +2022-12-09 13:56:43.386 plugin-container[6192:83675] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:56:43.387 plugin-container[6192:83675] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:56:43.391 plugin-container[6192:83675] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:56:43.391 plugin-container[6192:83675] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 13:56:43.391 plugin-container[6192:83672] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 13:56:43.391 plugin-container[6192:83672] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670590603856 Marionette INFO Marionette enabled +1670590603908 Marionette INFO Listening on port 62730 +Read port: 62730 +WebDriver BiDi listening on ws://127.0.0.1:62725 +1670590604813 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.error: Region.jsm: "Error fetching region" (new TypeError("NetworkError when attempting to fetch resource.", "")) +console.error: Region.jsm: "Failed to fetch region" (new Error("NO_RESULT", "resource://gre/modules/Region.sys.mjs", 415)) +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofiletGyVsy/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:62725/devtools/browser/6732503c-5eb7-4210-b1f7-d2a02a8d4a5e +1670590618214 Marionette INFO Stopped listening on port 62730 +1670590622559 geckodriver INFO Listening on 127.0.0.1:62739 +1670590623075 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "62740" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileuhzfn2" +1670593128358 geckodriver INFO Listening on 127.0.0.1:49222 +1670593128880 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "49223" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileDiBvPy" +1670593129717 Marionette INFO Marionette enabled +2022-12-09 14:38:49.853 plugin-container[1037:11231] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:38:49.854 plugin-container[1037:11231] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 14:38:49.862 plugin-container[1037:11231] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:38:49.862 plugin-container[1037:11231] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 14:38:49.864 plugin-container[1037:11234] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:38:49.864 plugin-container[1037:11234] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670593129868 Marionette INFO Listening on port 49230 +Read port: 49230 +WebDriver BiDi listening on ws://127.0.0.1:49223 +1670593130171 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileDiBvPy/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:49223/devtools/browser/2d37bf7f-8bad-4300-aaa6-5af440c11e10 +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +1670593281311 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670593313383 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670593319249 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +Exiting due to channel error. +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +1670593369569 geckodriver INFO Listening on 127.0.0.1:50410 +1670593369589 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50411" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileoYXB06" +2022-12-09 14:42:50.964 plugin-container[1299:14083] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:42:50.966 plugin-container[1299:14083] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 14:42:51.040 plugin-container[1299:14083] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:42:51.040 plugin-container[1299:14083] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 14:42:51.040 plugin-container[1299:14080] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:42:51.040 plugin-container[1299:14080] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670593371200 Marionette INFO Marionette enabled +1670593371286 Marionette INFO Listening on port 50424 +Read port: 50424 +WebDriver BiDi listening on ws://127.0.0.1:50411 +1670593372446 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileoYXB06/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50411/devtools/browser/0ba3f8b3-7cc6-4180-94b1-decd5552af3c +1670593405620 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +Exiting due to channel error. +1670593539820 geckodriver INFO Listening on 127.0.0.1:50964 +1670593540338 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "50965" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileOUjf9c" +1670593541224 Marionette INFO Marionette enabled +2022-12-09 14:45:41.337 plugin-container[1433:15822] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:45:41.338 plugin-container[1433:15822] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670593541340 Marionette INFO Listening on port 50970 +2022-12-09 14:45:41.342 plugin-container[1433:15822] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:45:41.342 plugin-container[1433:15822] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 14:45:41.343 plugin-container[1433:15852] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 14:45:41.343 plugin-container[1433:15852] nil host used in call to allowsAnyHTTPSCertificateForHost: +Read port: 50970 +WebDriver BiDi listening on ws://127.0.0.1:50965 +1670593541792 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileOUjf9c/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:50965/devtools/browser/36ad0a10-d44b-4522-af52-9ab620d00f8c +Exiting due to channel error. +Exiting due to channel error. +Exiting due to channel error. +1670595327207 geckodriver INFO Listening on 127.0.0.1:59387 +1670595327726 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "59388" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileF9pDS3" +1670595328478 Marionette INFO Marionette enabled +2022-12-09 15:15:28.626 plugin-container[3034:36370] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:15:28.628 plugin-container[3034:36370] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 15:15:28.639 plugin-container[3034:36370] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:15:28.639 plugin-container[3034:36370] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 15:15:28.640 plugin-container[3034:36372] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:15:28.640 plugin-container[3034:36372] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670595328705 Marionette INFO Listening on port 59393 +Read port: 59393 +WebDriver BiDi listening on ws://127.0.0.1:59388 +1670595329218 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileF9pDS3/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:59388/devtools/browser/a314e0e6-3ab6-4f31-9f2d-200913ccd35f +1670595334996 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670595364617 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595365455 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595366323 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670595367205 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595368083 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595368928 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595369779 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595370746 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +JavaScript error: , line 0: uncaught exception: Object +1670595388317 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595389612 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +JavaScript error: , line 0: uncaught exception: Object +1670595390900 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595392201 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595393766 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595395075 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595396507 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595397792 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595399102 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595400367 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595401652 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595402942 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595404248 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595405521 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595406837 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595408124 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670595409442 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +Exiting due to channel error. +Exiting due to channel error. +[GFX1-]: Receive IPC close with reason=AbnormalShutdown +Exiting due to channel error. +1670596741219 geckodriver INFO Listening on 127.0.0.1:60568 +1670596741730 mozrunner::runner INFO Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "--marionette" "--remote-debugging-port" "60569" "--remote-allow-hosts" "localhost" "-foreground" "-no-remote" "-profile" "/var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileJ010Dt" +2022-12-09 15:39:02.511 plugin-container[4221:51084] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:39:02.512 plugin-container[4221:51084] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670596742532 Marionette INFO Marionette enabled +2022-12-09 15:39:02.545 plugin-container[4221:51084] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:39:02.545 plugin-container[4221:51084] nil host used in call to allowsAnyHTTPSCertificateForHost: +2022-12-09 15:39:02.546 plugin-container[4221:51088] nil host used in call to allowsSpecificHTTPSCertificateForHost +2022-12-09 15:39:02.546 plugin-container[4221:51088] nil host used in call to allowsAnyHTTPSCertificateForHost: +1670596742677 Marionette INFO Listening on port 60575 +Read port: 60575 +WebDriver BiDi listening on ws://127.0.0.1:60569 +1670596743394 RemoteAgent WARN TLS certificate errors will be ignored for this session +console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at /var/folders/r3/4gr8207d4mq7bl5h34bn84hc0000gn/T/rust_mozprofileJ010Dt/search.json.mozlz4", (void 0))) +DevTools listening on ws://127.0.0.1:60569/devtools/browser/cb7fbdbc-f898-4604-a673-450b6f31be4e +console.error: Region.jsm: "Error fetching region" (new Error("TIMEOUT", "resource://gre/modules/Region.sys.mjs", 763)) +console.error: Region.jsm: "Failed to fetch region" (new Error("TIMEOUT", "resource://gre/modules/Region.sys.mjs", 415)) +1670596769772 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596770866 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596771781 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596772625 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596773474 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596774330 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596775175 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596776028 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596776869 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596777710 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596778546 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596779392 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596780240 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596781080 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596781974 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596782823 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596784085 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596787008 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596788287 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596789549 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596790816 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596792077 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596793341 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596794603 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596795877 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596797147 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596798485 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596799758 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596801085 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596802586 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596803920 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596805240 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596806990 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596808514 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596810132 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596811592 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596814404 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596839823 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596841539 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596843748 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596846236 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596856277 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596858991 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596861242 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596863279 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596865187 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596867519 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596870241 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596872907 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596875859 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596877767 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596880700 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596882791 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596887070 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596891001 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596892603 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596894928 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596898032 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596899721 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596902001 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596903846 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596906861 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596908985 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596911620 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596914218 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596917028 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596919950 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596922959 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596925191 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596929447 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596933102 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596990795 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596994388 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596996886 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670596999631 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597036910 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597040957 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597043205 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597051498 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597054417 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597057283 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597058955 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597060641 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597062153 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597063691 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597065216 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597066635 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597068129 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597072770 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597074328 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597077229 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597080452 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597086350 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597089568 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597091222 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597092695 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597094079 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597095370 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597097108 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597098657 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597099965 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597101235 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597102530 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597103830 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597105100 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597106363 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597107648 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597108918 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597110196 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597111468 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597112731 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597114020 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597115311 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597116585 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597117862 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597119157 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597120503 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597121929 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597123447 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597124807 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597126143 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597127676 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597129478 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597131332 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597153888 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597155596 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597157089 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597159098 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597161471 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597163426 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597165467 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597167713 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597169576 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597171469 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597174288 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597176561 Marionette WARN TimedPromise timed out after 500 ms: stacktrace: +TimedPromise/<@chrome://remote/content/marionette/sync.sys.mjs:220:24 +TimedPromise@chrome://remote/content/marionette/sync.sys.mjs:205:10 +interaction.flushEventLoop@chrome://remote/content/marionette/interaction.sys.mjs:425:10 +webdriverClickElement@chrome://remote/content/marionette/interaction.sys.mjs:173:31 +1670597179004 Marionette INFO Stopped listening on port 60575 diff --git a/axios-example/harvesting.sh b/axios-example/harvesting.sh new file mode 100644 index 0000000..9ddf0a9 --- /dev/null +++ b/axios-example/harvesting.sh @@ -0,0 +1,4 @@ +source bin/activate +flask run -p 6969 & +python3 ./meta.py & +python3 ./pics.py diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/LICENSE.rst b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/LICENSE.rst new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/METADATA new file mode 100644 index 0000000..9be4110 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/METADATA @@ -0,0 +1,126 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 2.1.2 +Summary: A simple framework for building complex web applications. +Home-page: https://palletsprojects.com/p/flask +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/flask/ +Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: Werkzeug (>=2.0) +Requires-Dist: Jinja2 (>=3.0) +Requires-Dist: itsdangerous (>=2.0) +Requires-Dist: click (>=8.0) +Requires-Dist: importlib-metadata (>=3.6.0) ; python_version < "3.10" +Provides-Extra: async +Requires-Dist: asgiref (>=3.2) ; extra == 'async' +Provides-Extra: dotenv +Requires-Dist: python-dotenv ; extra == 'dotenv' + +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +.. _WSGI: https://wsgi.readthedocs.io/ +.. _Werkzeug: https://werkzeug.palletsprojects.com/ +.. _Jinja: https://jinja.palletsprojects.com/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) + + +Contributing +------------ + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the `contributing guidelines`_. + +.. _contributing guidelines: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst + + +Donate +------ + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Website: https://palletsprojects.com/p/flask/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/RECORD new file mode 100644 index 0000000..8d4577d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/RECORD @@ -0,0 +1,52 @@ +../../../bin/flask,sha256=D0MxglDrmpyo8MR3iVaFP7dO-8Nur-9-7oFGFLMmUWc,244 +Flask-2.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Flask-2.1.2.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +Flask-2.1.2.dist-info/METADATA,sha256=V3wRBN5pAKumPcu41b-ePUWUQkdyka_WVPXwMKGvLGQ,3907 +Flask-2.1.2.dist-info/RECORD,, +Flask-2.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Flask-2.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +Flask-2.1.2.dist-info/entry_points.txt,sha256=s3MqQpduU25y4dq3ftBYD6bMVdVnbMpZP-sUNw0zw0k,41 +Flask-2.1.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=hutpl3wZCIHR-FckBdDZMe_pw89k7llUTj7c7t77cWc,2207 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-310.pyc,, +flask/__pycache__/__main__.cpython-310.pyc,, +flask/__pycache__/app.cpython-310.pyc,, +flask/__pycache__/blueprints.cpython-310.pyc,, +flask/__pycache__/cli.cpython-310.pyc,, +flask/__pycache__/config.cpython-310.pyc,, +flask/__pycache__/ctx.cpython-310.pyc,, +flask/__pycache__/debughelpers.cpython-310.pyc,, +flask/__pycache__/globals.cpython-310.pyc,, +flask/__pycache__/helpers.cpython-310.pyc,, +flask/__pycache__/logging.cpython-310.pyc,, +flask/__pycache__/scaffold.cpython-310.pyc,, +flask/__pycache__/sessions.cpython-310.pyc,, +flask/__pycache__/signals.cpython-310.pyc,, +flask/__pycache__/templating.cpython-310.pyc,, +flask/__pycache__/testing.cpython-310.pyc,, +flask/__pycache__/typing.cpython-310.pyc,, +flask/__pycache__/views.cpython-310.pyc,, +flask/__pycache__/wrappers.cpython-310.pyc,, +flask/app.py,sha256=b6_j0OtlrssZ05fMReHNwzSLN3M7mkI9LR8UWuhcm0g,82070 +flask/blueprints.py,sha256=W2C5eFciX2Zq8zJSKQHiQd488Ytcsrt6wcXSZ-rSU7c,23362 +flask/cli.py,sha256=eCZMiAFr6quTZo2pZ5RH2NBS1cQEZqLke9MCloOVIMA,31185 +flask/config.py,sha256=IWqHecH4poDxNEUg4U_ZA1CTlL5BKZDX3ofG4UGYyi0,12584 +flask/ctx.py,sha256=smANecq_Tr3FFi2UMDs3Nn-xYi9GhKrzZvFpkDqXtLM,18336 +flask/debughelpers.py,sha256=parkDxfxxGZZAOGSumyrGLCTKcws86lJ2X3RqikiwUE,6036 +flask/globals.py,sha256=cWd-R2hUH3VqPhnmQNww892tQS6Yjqg_wg8UvW1M7NM,1723 +flask/helpers.py,sha256=qkbHG_6-Ox_uDmmD8ZwA9k4nTI8Q8U5S_6QtXpzZCRg,29266 +flask/json/__init__.py,sha256=jZHbiHKOICmnMttYIhHYrCj2LeHjZY-J7KiYoorjc4I,10394 +flask/json/__pycache__/__init__.cpython-310.pyc,, +flask/json/__pycache__/tag.cpython-310.pyc,, +flask/json/tag.py,sha256=fys3HBLssWHuMAIJuTcf2K0bCtosePBKXIWASZEEjnU,8857 +flask/logging.py,sha256=1o_hirVGqdj7SBdETnhX7IAjklG89RXlrwz_2CjzQQE,2273 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/scaffold.py,sha256=vFn4R_sDhaWwxH77UGmRUWgE2p9tzj9VqRHG5dvE7wM,32545 +flask/sessions.py,sha256=y0f1WBTQqjebkjtiT6d0G_ejIvllsjzch5sq_NUoXec,15834 +flask/signals.py,sha256=H7QwDciK-dtBxinjKpexpglP0E6k0MJILiFWTItfmqU,2136 +flask/templating.py,sha256=6rcyoV-Z57uBGMB6_xl4LhQJHbF456naf-GU8pjQSPM,5659 +flask/testing.py,sha256=mfyDupACHNQinATGAcrqqDst9Ik4CnNg3rP9gvpUjks,10385 +flask/typing.py,sha256=P1x3WCUYE7ddMNCUVqr04V5EjJy4M0Osz1MfVM0xgMQ,2116 +flask/views.py,sha256=nhq31TRB5Z-z2mjFGZACaaB2Et5XPCmWhWxJxOvLWww,5948 +flask/wrappers.py,sha256=Vgs2HlC8WNUOELQasV-Xad8DFTFwJe3eUltZG9z4Cu8,5675 diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/entry_points.txt b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/entry_points.txt new file mode 100644 index 0000000..137232d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +flask = flask.cli:main diff --git a/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/top_level.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Flask-2.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +flask diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst new file mode 100644 index 0000000..c37cae4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA new file mode 100644 index 0000000..f54bb5c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA @@ -0,0 +1,113 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 3.1.2 +Summary: A very fast and expressive template engine. +Home-page: https://palletsprojects.com/p/jinja/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/jinja/ +Project-URL: Issue Tracker, https://github.com/pallets/jinja/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: MarkupSafe (>=2.0) +Provides-Extra: i18n +Requires-Dist: Babel (>=2.7) ; extra == 'i18n' + +Jinja +===== + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Jinja2 + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +In A Nutshell +------------- + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} + + {% endblock %} + + +Donate +------ + +The Pallets organization develops and supports Jinja and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://jinja.palletsprojects.com/ +- Changes: https://jinja.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Jinja2/ +- Source Code: https://github.com/pallets/jinja/ +- Issue Tracker: https://github.com/pallets/jinja/issues/ +- Website: https://palletsprojects.com/p/jinja/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD new file mode 100644 index 0000000..b1968f1 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD @@ -0,0 +1,59 @@ +Jinja2-3.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Jinja2-3.1.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Jinja2-3.1.2.dist-info/METADATA,sha256=PZ6v2SIidMNixR7MRUX9f7ZWsPwtXanknqiZUmRbh4U,3539 +Jinja2-3.1.2.dist-info/RECORD,, +Jinja2-3.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Jinja2-3.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +Jinja2-3.1.2.dist-info/entry_points.txt,sha256=zRd62fbqIyfUpsRtU7EVIFyiu1tPwfgO7EvPErnxgTE,59 +Jinja2-3.1.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=8vGduD8ytwgD6GDSqpYc2m3aU-T7PKOAddvVXgGr_Fs,1927 +jinja2/__pycache__/__init__.cpython-310.pyc,, +jinja2/__pycache__/_identifier.cpython-310.pyc,, +jinja2/__pycache__/async_utils.cpython-310.pyc,, +jinja2/__pycache__/bccache.cpython-310.pyc,, +jinja2/__pycache__/compiler.cpython-310.pyc,, +jinja2/__pycache__/constants.cpython-310.pyc,, +jinja2/__pycache__/debug.cpython-310.pyc,, +jinja2/__pycache__/defaults.cpython-310.pyc,, +jinja2/__pycache__/environment.cpython-310.pyc,, +jinja2/__pycache__/exceptions.cpython-310.pyc,, +jinja2/__pycache__/ext.cpython-310.pyc,, +jinja2/__pycache__/filters.cpython-310.pyc,, +jinja2/__pycache__/idtracking.cpython-310.pyc,, +jinja2/__pycache__/lexer.cpython-310.pyc,, +jinja2/__pycache__/loaders.cpython-310.pyc,, +jinja2/__pycache__/meta.cpython-310.pyc,, +jinja2/__pycache__/nativetypes.cpython-310.pyc,, +jinja2/__pycache__/nodes.cpython-310.pyc,, +jinja2/__pycache__/optimizer.cpython-310.pyc,, +jinja2/__pycache__/parser.cpython-310.pyc,, +jinja2/__pycache__/runtime.cpython-310.pyc,, +jinja2/__pycache__/sandbox.cpython-310.pyc,, +jinja2/__pycache__/tests.cpython-310.pyc,, +jinja2/__pycache__/utils.cpython-310.pyc,, +jinja2/__pycache__/visitor.cpython-310.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=dHlbTeaxFPtAOQEYOGYh_PHcDT0rsDaUJAFDl_0XtTg,2472 +jinja2/bccache.py,sha256=mhz5xtLxCcHRAa56azOhphIAe19u1we0ojifNMClDio,14061 +jinja2/compiler.py,sha256=Gs-N8ThJ7OWK4-reKoO8Wh1ZXz95MVphBKNVf75qBr8,72172 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=iWJ432RadxJNnaMOPrjIDInz50UEgni3_HKuFXi2vuQ,6299 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=6uHIcc7ZblqOMdx_uYNKqRnnwAF0_nzbyeMP9FFtuh4,61349 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=ivr3P7LKbddiXDVez20EflcO3q2aHQwz9P_PgWGHVqE,31502 +jinja2/filters.py,sha256=9js1V-h2RlyW90IhLiBGLM2U-k6SCy2F4BUUMgB3K9Q,53509 +jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704 +jinja2/lexer.py,sha256=DW2nX9zk-6MWp65YR2bqqj0xqCvLtD-u9NWT8AnFRxQ,29726 +jinja2/loaders.py,sha256=BfptfvTVpClUd-leMkHczdyPNYFzp_n7PKOJ98iyHOg,23207 +jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396 +jinja2/nativetypes.py,sha256=DXgORDPRmVWgy034H0xL8eF7qYoK3DrMxs-935d0Fzk,4226 +jinja2/nodes.py,sha256=i34GPRAZexXMT6bwuf5SEyvdmS-bRCy9KMjwN5O6pjk,34550 +jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650 +jinja2/parser.py,sha256=nHd-DFHbiygvfaPtm9rcQXJChZG7DPsWfiEsqfwKerY,39595 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=5CmD5BjbEJxSiDNTFBeKCaq8qU4aYD2v6q2EluyExms,33476 +jinja2/sandbox.py,sha256=Y0xZeXQnH6EX5VjaV2YixESxoepnRbW_3UeQosaBU3M,14584 +jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905 +jinja2/utils.py,sha256=u9jXESxGn8ATZNVolwmkjUVu4SA-tLgV0W7PcSfPfdQ,23965 +jinja2/visitor.py,sha256=MH14C6yq24G_KVtWzjwaI7Wg14PCJIYlWW1kpkxYak0,3568 diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt new file mode 100644 index 0000000..7b9666c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract[i18n] diff --git a/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt new file mode 100644 index 0000000..7f7afbf --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/LICENSE.rst b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/LICENSE.rst new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/METADATA new file mode 100644 index 0000000..485a5e0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/METADATA @@ -0,0 +1,101 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 2.1.1 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/markupsafe/ +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + + >>> # escape replaces special characters and wraps in Markup + >>> escape("") + Markup('<script>alert(document.cookie);</script>') + + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup("Hello") + Markup('hello') + + >>> escape(Markup("Hello")) + Markup('hello') + + >>> # Markup is a str subclass + >>> # methods and operators escape their arguments + >>> template = Markup("Hello {name}") + >>> template.format(name='"World"') + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Website: https://palletsprojects.com/p/markupsafe/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/RECORD new file mode 100644 index 0000000..d5791f5 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/RECORD @@ -0,0 +1,15 @@ +MarkupSafe-2.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-2.1.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-2.1.1.dist-info/METADATA,sha256=DC93VszmzjLQcrVChRUjtW4XbUwjTdbaplpgdlbFdbs,3242 +MarkupSafe-2.1.1.dist-info/RECORD,, +MarkupSafe-2.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +MarkupSafe-2.1.1.dist-info/WHEEL,sha256=QN3MNOFrRIeE9ccPTe5mH4Q_A2DBDdD7_qUigvuJeQU,111 +MarkupSafe-2.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=xfaUQkKNRTdYWe6HnnJ2HjguFmS-C_0H6g8-Q9VAfkQ,9284 +markupsafe/__pycache__/__init__.cpython-310.pyc,, +markupsafe/__pycache__/_native.cpython-310.pyc,, +markupsafe/_native.py,sha256=GR86Qvo_GcgKmKreA1WmYN9ud17OFwkww8E-fiW-57s,1713 +markupsafe/_speedups.c,sha256=X2XvQVtIdcK4Usz70BvkzoOfjTCmQlDkkjYSn-swE0g,7083 +markupsafe/_speedups.cpython-310-darwin.so,sha256=RrUcL36CQAvdE7Xf4OcvU3CVuQ4qkgDwylh52HXTyHM,35136 +markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/WHEEL new file mode 100644 index 0000000..0e82f60 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: false +Tag: cp310-cp310-macosx_10_9_x86_64 + diff --git a/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/top_level.txt new file mode 100644 index 0000000..75bf729 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/MarkupSafe-2.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/LICENSE new file mode 100644 index 0000000..04b6b1f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/LICENSE @@ -0,0 +1,22 @@ +Copyright 2006 Dan-Haim. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. Neither the name of Dan Haim nor the names of his contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/METADATA new file mode 100644 index 0000000..ae2ae34 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/METADATA @@ -0,0 +1,321 @@ +Metadata-Version: 2.1 +Name: PySocks +Version: 1.7.1 +Summary: A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information. +Home-page: https://github.com/Anorov/PySocks +Author: Anorov +Author-email: anorov.vorona@gmail.com +License: BSD +Keywords: socks,proxy +Platform: UNKNOWN +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Description-Content-Type: text/markdown + +PySocks +======= + +PySocks lets you send traffic through SOCKS and HTTP proxy servers. It is a modern fork of [SocksiPy](http://socksipy.sourceforge.net/) with bug fixes and extra features. + +Acts as a drop-in replacement to the socket module. Seamlessly configure SOCKS proxies for any socket object by calling `socket_object.set_proxy()`. + +---------------- + +Features +======== + +* SOCKS proxy client for Python 2.7 and 3.4+ +* TCP supported +* UDP mostly supported (issues may occur in some edge cases) +* HTTP proxy client included but not supported or recommended (you should use urllib2's or requests' own HTTP proxy interface) +* urllib2 handler included. `pip install` / `setup.py install` will automatically install the `sockshandler` module. + +Installation +============ + + pip install PySocks + +Or download the tarball / `git clone` and... + + python setup.py install + +These will install both the `socks` and `sockshandler` modules. + +Alternatively, include just `socks.py` in your project. + +-------------------------------------------- + +*Warning:* PySocks/SocksiPy only supports HTTP proxies that use CONNECT tunneling. Certain HTTP proxies may not work with this library. If you wish to use HTTP (not SOCKS) proxies, it is recommended that you rely on your HTTP client's native proxy support (`proxies` dict for `requests`, or `urllib2.ProxyHandler` for `urllib2`) instead. + +-------------------------------------------- + +Usage +===== + +## socks.socksocket ## + + import socks + + s = socks.socksocket() # Same API as socket.socket in the standard lib + + s.set_proxy(socks.SOCKS5, "localhost") # SOCKS4 and SOCKS5 use port 1080 by default + # Or + s.set_proxy(socks.SOCKS4, "localhost", 4444) + # Or + s.set_proxy(socks.HTTP, "5.5.5.5", 8888) + + # Can be treated identical to a regular socket object + s.connect(("www.somesite.com", 80)) + s.sendall("GET / HTTP/1.1 ...") + print s.recv(4096) + +## Monkeypatching ## + +To monkeypatch the entire standard library with a single default proxy: + + import urllib2 + import socket + import socks + + socks.set_default_proxy(socks.SOCKS5, "localhost") + socket.socket = socks.socksocket + + urllib2.urlopen("http://www.somesite.com/") # All requests will pass through the SOCKS proxy + +Note that monkeypatching may not work for all standard modules or for all third party modules, and generally isn't recommended. Monkeypatching is usually an anti-pattern in Python. + +## urllib2 Handler ## + +Example use case with the `sockshandler` urllib2 handler. Note that you must import both `socks` and `sockshandler`, as the handler is its own module separate from PySocks. The module is included in the PyPI package. + + import urllib2 + import socks + from sockshandler import SocksiPyHandler + + opener = urllib2.build_opener(SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 9050)) + print opener.open("http://www.somesite.com/") # All requests made by the opener will pass through the SOCKS proxy + +-------------------------------------------- + +Original SocksiPy README attached below, amended to reflect API changes. + +-------------------------------------------- + +SocksiPy + +A Python SOCKS module. + +(C) 2006 Dan-Haim. All rights reserved. + +See LICENSE file for details. + + +*WHAT IS A SOCKS PROXY?* + +A SOCKS proxy is a proxy server at the TCP level. In other words, it acts as +a tunnel, relaying all traffic going through it without modifying it. +SOCKS proxies can be used to relay traffic using any network protocol that +uses TCP. + +*WHAT IS SOCKSIPY?* + +This Python module allows you to create TCP connections through a SOCKS +proxy without any special effort. +It also supports relaying UDP packets with a SOCKS5 proxy. + +*PROXY COMPATIBILITY* + +SocksiPy is compatible with three different types of proxies: + +1. SOCKS Version 4 (SOCKS4), including the SOCKS4a extension. +2. SOCKS Version 5 (SOCKS5). +3. HTTP Proxies which support tunneling using the CONNECT method. + +*SYSTEM REQUIREMENTS* + +Being written in Python, SocksiPy can run on any platform that has a Python +interpreter and TCP/IP support. +This module has been tested with Python 2.3 and should work with greater versions +just as well. + + +INSTALLATION +------------- + +Simply copy the file "socks.py" to your Python's `lib/site-packages` directory, +and you're ready to go. [Editor's note: it is better to use `python setup.py install` for PySocks] + + +USAGE +------ + +First load the socks module with the command: + + >>> import socks + >>> + +The socks module provides a class called `socksocket`, which is the base to all of the module's functionality. + +The `socksocket` object has the same initialization parameters as the normal socket +object to ensure maximal compatibility, however it should be noted that `socksocket` will only function with family being `AF_INET` and +type being either `SOCK_STREAM` or `SOCK_DGRAM`. +Generally, it is best to initialize the `socksocket` object with no parameters + + >>> s = socks.socksocket() + >>> + +The `socksocket` object has an interface which is very similiar to socket's (in fact +the `socksocket` class is derived from socket) with a few extra methods. +To select the proxy server you would like to use, use the `set_proxy` method, whose +syntax is: + + set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]]) + +Explanation of the parameters: + +`proxy_type` - The type of the proxy server. This can be one of three possible +choices: `PROXY_TYPE_SOCKS4`, `PROXY_TYPE_SOCKS5` and `PROXY_TYPE_HTTP` for SOCKS4, +SOCKS5 and HTTP servers respectively. `SOCKS4`, `SOCKS5`, and `HTTP` are all aliases, respectively. + +`addr` - The IP address or DNS name of the proxy server. + +`port` - The port of the proxy server. Defaults to 1080 for socks and 8080 for http. + +`rdns` - This is a boolean flag than modifies the behavior regarding DNS resolving. +If it is set to True, DNS resolving will be preformed remotely, on the server. +If it is set to False, DNS resolving will be preformed locally. Please note that +setting this to True with SOCKS4 servers actually use an extension to the protocol, +called SOCKS4a, which may not be supported on all servers (SOCKS5 and http servers +always support DNS). The default is True. + +`username` - For SOCKS5 servers, this allows simple username / password authentication +with the server. For SOCKS4 servers, this parameter will be sent as the userid. +This parameter is ignored if an HTTP server is being used. If it is not provided, +authentication will not be used (servers may accept unauthenticated requests). + +`password` - This parameter is valid only for SOCKS5 servers and specifies the +respective password for the username provided. + +Example of usage: + + >>> s.set_proxy(socks.SOCKS5, "socks.example.com") # uses default port 1080 + >>> s.set_proxy(socks.SOCKS4, "socks.test.com", 1081) + +After the set_proxy method has been called, simply call the connect method with the +traditional parameters to establish a connection through the proxy: + + >>> s.connect(("www.sourceforge.net", 80)) + >>> + +Connection will take a bit longer to allow negotiation with the proxy server. +Please note that calling connect without calling `set_proxy` earlier will connect +without a proxy (just like a regular socket). + +Errors: Any errors in the connection process will trigger exceptions. The exception +may either be generated by the underlying socket layer or may be custom module +exceptions, whose details follow: + +class `ProxyError` - This is a base exception class. It is not raised directly but +rather all other exception classes raised by this module are derived from it. +This allows an easy way to catch all proxy-related errors. It descends from `IOError`. + +All `ProxyError` exceptions have an attribute `socket_err`, which will contain either a +caught `socket.error` exception, or `None` if there wasn't any. + +class `GeneralProxyError` - When thrown, it indicates a problem which does not fall +into another category. + +* `Sent invalid data` - This error means that unexpected data has been received from +the server. The most common reason is that the server specified as the proxy is +not really a SOCKS4/SOCKS5/HTTP proxy, or maybe the proxy type specified is wrong. + +* `Connection closed unexpectedly` - The proxy server unexpectedly closed the connection. +This may indicate that the proxy server is experiencing network or software problems. + +* `Bad proxy type` - This will be raised if the type of the proxy supplied to the +set_proxy function was not one of `SOCKS4`/`SOCKS5`/`HTTP`. + +* `Bad input` - This will be raised if the `connect()` method is called with bad input +parameters. + +class `SOCKS5AuthError` - This indicates that the connection through a SOCKS5 server +failed due to an authentication problem. + +* `Authentication is required` - This will happen if you use a SOCKS5 server which +requires authentication without providing a username / password at all. + +* `All offered authentication methods were rejected` - This will happen if the proxy +requires a special authentication method which is not supported by this module. + +* `Unknown username or invalid password` - Self descriptive. + +class `SOCKS5Error` - This will be raised for SOCKS5 errors which are not related to +authentication. +The parameter is a tuple containing a code, as given by the server, +and a description of the +error. The possible errors, according to the RFC, are: + +* `0x01` - General SOCKS server failure - If for any reason the proxy server is unable to +fulfill your request (internal server error). +* `0x02` - connection not allowed by ruleset - If the address you're trying to connect to +is blacklisted on the server or requires authentication. +* `0x03` - Network unreachable - The target could not be contacted. A router on the network +had replied with a destination net unreachable error. +* `0x04` - Host unreachable - The target could not be contacted. A router on the network +had replied with a destination host unreachable error. +* `0x05` - Connection refused - The target server has actively refused the connection +(the requested port is closed). +* `0x06` - TTL expired - The TTL value of the SYN packet from the proxy to the target server +has expired. This usually means that there are network problems causing the packet +to be caught in a router-to-router "ping-pong". +* `0x07` - Command not supported - For instance if the server does not support UDP. +* `0x08` - Address type not supported - The client has provided an invalid address type. +When using this module, this error should not occur. + +class `SOCKS4Error` - This will be raised for SOCKS4 errors. The parameter is a tuple +containing a code and a description of the error, as given by the server. The +possible error, according to the specification are: + +* `0x5B` - Request rejected or failed - Will be raised in the event of an failure for any +reason other then the two mentioned next. +* `0x5C` - request rejected because SOCKS server cannot connect to identd on the client - +The Socks server had tried an ident lookup on your computer and has failed. In this +case you should run an identd server and/or configure your firewall to allow incoming +connections to local port 113 from the remote server. +* `0x5D` - request rejected because the client program and identd report different user-ids - +The Socks server had performed an ident lookup on your computer and has received a +different userid than the one you have provided. Change your userid (through the +username parameter of the set_proxy method) to match and try again. + +class `HTTPError` - This will be raised for HTTP errors. The message will contain +the HTTP status code and provided error message. + +After establishing the connection, the object behaves like a standard socket. + +Methods like `makefile()` and `settimeout()` should behave just like regular sockets. +Call the `close()` method to close the connection. + +In addition to the `socksocket` class, an additional function worth mentioning is the +`set_default_proxy` function. The parameters are the same as the `set_proxy` method. +This function will set default proxy settings for newly created `socksocket` objects, +in which the proxy settings haven't been changed via the `set_proxy` method. +This is quite useful if you wish to force 3rd party modules to use a SOCKS proxy, +by overriding the socket object. +For example: + + >>> socks.set_default_proxy(socks.SOCKS5, "socks.example.com") + >>> socket.socket = socks.socksocket + >>> urllib.urlopen("http://www.sourceforge.net/") + + +PROBLEMS +--------- + +Please open a GitHub issue at https://github.com/Anorov/PySocks + + diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/RECORD new file mode 100644 index 0000000..c7950f2 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/RECORD @@ -0,0 +1,10 @@ +PySocks-1.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +PySocks-1.7.1.dist-info/LICENSE,sha256=cCfiFOAU63i3rcwc7aWspxOnn8T2oMUsnaWz5wfm_-k,1401 +PySocks-1.7.1.dist-info/METADATA,sha256=zbQMizjPOOP4DhEiEX24XXjNrYuIxF9UGUpN0uFDB6Y,13235 +PySocks-1.7.1.dist-info/RECORD,, +PySocks-1.7.1.dist-info/WHEEL,sha256=t_MpApv386-8PVts2R6wsTifdIn0vbUDTVv61IbqFC8,92 +PySocks-1.7.1.dist-info/top_level.txt,sha256=TKSOIfCFBoK9EY8FBYbYqC3PWd3--G15ph9n8-QHPDk,19 +__pycache__/socks.cpython-310.pyc,, +__pycache__/sockshandler.cpython-310.pyc,, +socks.py,sha256=xOYn27t9IGrbTBzWsUUuPa0YBuplgiUykzkOB5V5iFY,31086 +sockshandler.py,sha256=2SYGj-pwt1kjgLoZAmyeaEXCeZDWRmfVS_QG6kErGtY,3966 diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/WHEEL new file mode 100644 index 0000000..129a673 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.33.3) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/top_level.txt new file mode 100644 index 0000000..9476163 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/PySocks-1.7.1.dist-info/top_level.txt @@ -0,0 +1,2 @@ +socks +sockshandler diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/LICENSE.rst b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/LICENSE.rst new file mode 100644 index 0000000..c37cae4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/METADATA new file mode 100644 index 0000000..7247470 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/METADATA @@ -0,0 +1,128 @@ +Metadata-Version: 2.1 +Name: Werkzeug +Version: 2.1.2 +Summary: The comprehensive WSGI web application library. +Home-page: https://palletsprojects.com/p/werkzeug/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://werkzeug.palletsprojects.com/ +Project-URL: Changes, https://werkzeug.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/werkzeug/ +Project-URL: Issue Tracker, https://github.com/pallets/werkzeug/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Provides-Extra: watchdog +Requires-Dist: watchdog ; extra == 'watchdog' + +Werkzeug +======== + +*werkzeug* German noun: "tool". Etymology: *werk* ("work"), *zeug* ("stuff") + +Werkzeug is a comprehensive `WSGI`_ web application library. It began as +a simple collection of various utilities for WSGI applications and has +become one of the most advanced WSGI utility libraries. + +It includes: + +- An interactive debugger that allows inspecting stack traces and + source code in the browser with an interactive interpreter for any + frame in the stack. +- A full-featured request object with objects to interact with + headers, query args, form data, files, and cookies. +- A response object that can wrap other WSGI applications and handle + streaming data. +- A routing system for matching URLs to endpoints and generating URLs + for endpoints, with an extensible system for capturing variables + from URLs. +- HTTP utilities to handle entity tags, cache control, dates, user + agents, cookies, files, and more. +- A threaded WSGI server for use while developing applications + locally. +- A test client for simulating HTTP requests during testing without + requiring running a server. + +Werkzeug doesn't enforce any dependencies. It is up to the developer to +choose a template engine, database adapter, and even how to handle +requests. It can be used to build all sorts of end user applications +such as blogs, wikis, or bulletin boards. + +`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while +providing more structure and patterns for defining powerful +applications. + +.. _WSGI: https://wsgi.readthedocs.io/en/latest/ +.. _Flask: https://www.palletsprojects.com/p/flask/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U Werkzeug + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + from werkzeug.wrappers import Request, Response + + @Request.application + def application(request): + return Response('Hello, World!') + + if __name__ == '__main__': + from werkzeug.serving import run_simple + run_simple('localhost', 4000, application) + + +Donate +------ + +The Pallets organization develops and supports Werkzeug and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://werkzeug.palletsprojects.com/ +- Changes: https://werkzeug.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Werkzeug/ +- Source Code: https://github.com/pallets/werkzeug/ +- Issue Tracker: https://github.com/pallets/werkzeug/issues/ +- Website: https://palletsprojects.com/p/werkzeug/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/RECORD new file mode 100644 index 0000000..821319c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/RECORD @@ -0,0 +1,87 @@ +Werkzeug-2.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Werkzeug-2.1.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Werkzeug-2.1.2.dist-info/METADATA,sha256=vWBYPD9d_Qzl4WAupfJ5Fy_ep7pqMPnGvkSLYiCi4B0,4400 +Werkzeug-2.1.2.dist-info/RECORD,, +Werkzeug-2.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Werkzeug-2.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +Werkzeug-2.1.2.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 +werkzeug/__init__.py,sha256=BtM-3LM8iob4OwPY693-LqZ5RcnDS4iftOqBK28uZ2k,188 +werkzeug/__pycache__/__init__.cpython-310.pyc,, +werkzeug/__pycache__/_internal.cpython-310.pyc,, +werkzeug/__pycache__/_reloader.cpython-310.pyc,, +werkzeug/__pycache__/datastructures.cpython-310.pyc,, +werkzeug/__pycache__/exceptions.cpython-310.pyc,, +werkzeug/__pycache__/formparser.cpython-310.pyc,, +werkzeug/__pycache__/http.cpython-310.pyc,, +werkzeug/__pycache__/local.cpython-310.pyc,, +werkzeug/__pycache__/routing.cpython-310.pyc,, +werkzeug/__pycache__/security.cpython-310.pyc,, +werkzeug/__pycache__/serving.cpython-310.pyc,, +werkzeug/__pycache__/test.cpython-310.pyc,, +werkzeug/__pycache__/testapp.cpython-310.pyc,, +werkzeug/__pycache__/urls.cpython-310.pyc,, +werkzeug/__pycache__/user_agent.cpython-310.pyc,, +werkzeug/__pycache__/utils.cpython-310.pyc,, +werkzeug/__pycache__/wsgi.cpython-310.pyc,, +werkzeug/_internal.py,sha256=g8PHJz2z39I3x0vwTvTKbXIg0eUQqGF9UtUzDMWT0Qw,16222 +werkzeug/_reloader.py,sha256=lYStlIDduTxBOB8BSozy_44HQ7YT5fup-x3uuac1-2o,14331 +werkzeug/datastructures.py,sha256=Sk5gYGJbgvwpM-5IursyEWwo815RB5NAs2wFcTjHG0M,97018 +werkzeug/datastructures.pyi,sha256=L7MfJjHrEjKuAZ57w5d2eaiUIWYya52crapklFnKUz0,34493 +werkzeug/debug/__init__.py,sha256=Qds7CmReDr13XUaKYvcwnGNBQp6d86ooGV_to2Uw0C0,17730 +werkzeug/debug/__pycache__/__init__.cpython-310.pyc,, +werkzeug/debug/__pycache__/console.cpython-310.pyc,, +werkzeug/debug/__pycache__/repr.cpython-310.pyc,, +werkzeug/debug/__pycache__/tbtools.cpython-310.pyc,, +werkzeug/debug/console.py,sha256=08mKGZLMsrd2E-0qD82J5knUbI2DomHXUQ5z0550a_o,6082 +werkzeug/debug/repr.py,sha256=Mp911LMRzZUoNvrCLQfKKpQZbNKdIM8VbjzJQjBkdsM,9481 +werkzeug/debug/shared/ICON_LICENSE.md,sha256=DhA6Y1gUl5Jwfg0NFN9Rj4VWITt8tUx0IvdGf0ux9-s,222 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/debugger.js,sha256=tg42SZs1SVmYWZ-_Fj5ELK5-FLHnGNQrei0K2By8Bw8,10521 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +werkzeug/debug/shared/style.css,sha256=-xSxzUEZGw_IqlDR5iZxitNl8LQUjBM-_Y4UAvXVH8g,6078 +werkzeug/debug/tbtools.py,sha256=cBsPKCrB0FRT8i5EUdGo0A8MStWSj7O3Jk40r7Ll3ok,12633 +werkzeug/exceptions.py,sha256=5nzjr4AN_J-jtkT2FgDIm8SUiC0tjzWcROXse06H6a8,26498 +werkzeug/formparser.py,sha256=rLEu_ZwVpvqshZg6E4Qiv36QsmzmCytTijBeGX3dDGk,16056 +werkzeug/http.py,sha256=RUwj0JM1Em3LHyqyXSJOkdtBOT24mJlGFbklqo3PWDY,44602 +werkzeug/local.py,sha256=cj0M4BzMGdg_CD-H3osv9Zf9by4qY-BzAD68bxp979Q,18343 +werkzeug/middleware/__init__.py,sha256=qfqgdT5npwG9ses3-FXQJf3aB95JYP1zchetH_T3PUw,500 +werkzeug/middleware/__pycache__/__init__.cpython-310.pyc,, +werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc,, +werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc,, +werkzeug/middleware/__pycache__/lint.cpython-310.pyc,, +werkzeug/middleware/__pycache__/profiler.cpython-310.pyc,, +werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc,, +werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc,, +werkzeug/middleware/dispatcher.py,sha256=Fh_w-KyWnTSYF-Lfv5dimQ7THSS7afPAZMmvc4zF1gg,2580 +werkzeug/middleware/http_proxy.py,sha256=HE8VyhS7CR-E1O6_9b68huv8FLgGGR1DLYqkS3Xcp3Q,7558 +werkzeug/middleware/lint.py,sha256=L4ISeRPhFbrMWt8CFHHExyvuWxE3CyqbfD5hTQKkVjA,13966 +werkzeug/middleware/profiler.py,sha256=QkXk7cqnaPnF8wQu-5SyPCIOT3_kdABUBorQOghVNOA,4899 +werkzeug/middleware/proxy_fix.py,sha256=l7LC_LDu0Yd4SvUxS5SFigAJMzcIOGm6LNKl9IXJBSU,6974 +werkzeug/middleware/shared_data.py,sha256=fXjrEkuqxUVLG1DLrOdQLc96QQdjftCBZ1oM5oK89h4,9528 +werkzeug/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/routing.py,sha256=zopf1P3MG-atd33YdBwIO49AnJ7nem5SKQig5FIhKEI,84346 +werkzeug/sansio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/sansio/__pycache__/__init__.cpython-310.pyc,, +werkzeug/sansio/__pycache__/multipart.cpython-310.pyc,, +werkzeug/sansio/__pycache__/request.cpython-310.pyc,, +werkzeug/sansio/__pycache__/response.cpython-310.pyc,, +werkzeug/sansio/__pycache__/utils.cpython-310.pyc,, +werkzeug/sansio/multipart.py,sha256=BRjBk_mCPjSJzwNVvBgmrJGk3QxA9pYfsgzFki28bxc,8751 +werkzeug/sansio/request.py,sha256=6xhrNJAqScdbBF5i7HN-Y_1XjJ04wQtBKOsZuCy0AYw,20176 +werkzeug/sansio/response.py,sha256=zvCq9HSBBZGBd5Gg412BY9RZIwnKsJl5Kzfd3Kl9sSo,26098 +werkzeug/sansio/utils.py,sha256=V5v-UUnX8pm4RehP9Tt_NiUSOJGJGUvKjlW0eOIQldM,4164 +werkzeug/security.py,sha256=vrBofh4WZZoUo1eAdJ6F1DrzVRlYauGS2CUDYpbQKj8,4658 +werkzeug/serving.py,sha256=aL-dIwzwO_-UuUs0cKwYFOynUWVmYcaDjz713Wy_BHE,38337 +werkzeug/test.py,sha256=7Ur4IinGCk9k5WCNk6x-mr2JrnupvKRXt6n-qNfo9oE,47841 +werkzeug/testapp.py,sha256=p-2lMyvaHXzP1lau0tUAJTbW4STogoMpXFyCkeRBkAI,9397 +werkzeug/urls.py,sha256=Q9Si-eVh7yxk3rwkzrwGRm146FXVXgg9lBP3k0HUfVM,36600 +werkzeug/user_agent.py,sha256=WclZhpvgLurMF45hsioSbS75H1Zb4iMQGKN3_yZ2oKo,1420 +werkzeug/utils.py,sha256=5HGm_5WSKBTVVl8IgvA-b-jL7gjT-LHWXH0ZKzCCI0I,24932 +werkzeug/wrappers/__init__.py,sha256=kGyK7rOud3qCxll_jFyW15YarJhj1xtdf3ocx9ZheB8,120 +werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc,, +werkzeug/wrappers/__pycache__/request.cpython-310.pyc,, +werkzeug/wrappers/__pycache__/response.cpython-310.pyc,, +werkzeug/wrappers/request.py,sha256=UQ559KkGS0Po6HTBgvKMlk1_AsNw5zstzm8o_dRrfdQ,23415 +werkzeug/wrappers/response.py,sha256=c2HUXrrt5Sf8-XEB1fUXxm6jp7Lu80KR0A_tbQFvw1Q,34750 +werkzeug/wsgi.py,sha256=L7s5-Rlt7BRVEZ1m81MaenGfMDP7yL3p1Kxt9Yssqzg,33727 diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/top_level.txt new file mode 100644 index 0000000..6fe8da8 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/Werkzeug-2.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +werkzeug diff --git a/axios-example/lib/python3.10/site-packages/_distutils_hack/__init__.py b/axios-example/lib/python3.10/site-packages/_distutils_hack/__init__.py new file mode 100644 index 0000000..f987a53 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/_distutils_hack/__init__.py @@ -0,0 +1,222 @@ +# don't import any costly modules +import sys +import os + + +is_pypy = '__pypy__' in sys.builtin_module_names + + +def warn_distutils_present(): + if 'distutils' not in sys.modules: + return + if is_pypy and sys.version_info < (3, 7): + # PyPy for 3.6 unconditionally imports distutils, so bypass the warning + # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 + return + import warnings + + warnings.warn( + "Distutils was imported before Setuptools, but importing Setuptools " + "also replaces the `distutils` module in `sys.modules`. This may lead " + "to undesirable behaviors or errors. To avoid these issues, avoid " + "using distutils directly, ensure that setuptools is installed in the " + "traditional way (e.g. not an editable install), and/or make sure " + "that setuptools is always imported before distutils." + ) + + +def clear_distutils(): + if 'distutils' not in sys.modules: + return + import warnings + + warnings.warn("Setuptools is replacing distutils.") + mods = [ + name + for name in sys.modules + if name == "distutils" or name.startswith("distutils.") + ] + for name in mods: + del sys.modules[name] + + +def enabled(): + """ + Allow selection of distutils by environment variable. + """ + which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local') + return which == 'local' + + +def ensure_local_distutils(): + import importlib + + clear_distutils() + + # With the DistutilsMetaFinder in place, + # perform an import to cause distutils to be + # loaded from setuptools._distutils. Ref #2906. + with shim(): + importlib.import_module('distutils') + + # check that submodules load as expected + core = importlib.import_module('distutils.core') + assert '_distutils' in core.__file__, core.__file__ + assert 'setuptools._distutils.log' not in sys.modules + + +def do_override(): + """ + Ensure that the local copy of distutils is preferred over stdlib. + + See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 + for more motivation. + """ + if enabled(): + warn_distutils_present() + ensure_local_distutils() + + +class _TrivialRe: + def __init__(self, *patterns): + self._patterns = patterns + + def match(self, string): + return all(pat in string for pat in self._patterns) + + +class DistutilsMetaFinder: + def find_spec(self, fullname, path, target=None): + # optimization: only consider top level modules and those + # found in the CPython test suite. + if path is not None and not fullname.startswith('test.'): + return + + method_name = 'spec_for_{fullname}'.format(**locals()) + method = getattr(self, method_name, lambda: None) + return method() + + def spec_for_distutils(self): + if self.is_cpython(): + return + + import importlib + import importlib.abc + import importlib.util + + try: + mod = importlib.import_module('setuptools._distutils') + except Exception: + # There are a couple of cases where setuptools._distutils + # may not be present: + # - An older Setuptools without a local distutils is + # taking precedence. Ref #2957. + # - Path manipulation during sitecustomize removes + # setuptools from the path but only after the hook + # has been loaded. Ref #2980. + # In either case, fall back to stdlib behavior. + return + + class DistutilsLoader(importlib.abc.Loader): + def create_module(self, spec): + mod.__name__ = 'distutils' + return mod + + def exec_module(self, module): + pass + + return importlib.util.spec_from_loader( + 'distutils', DistutilsLoader(), origin=mod.__file__ + ) + + @staticmethod + def is_cpython(): + """ + Suppress supplying distutils for CPython (build and tests). + Ref #2965 and #3007. + """ + return os.path.isfile('pybuilddir.txt') + + def spec_for_pip(self): + """ + Ensure stdlib distutils when running under pip. + See pypa/pip#8761 for rationale. + """ + if self.pip_imported_during_build(): + return + clear_distutils() + self.spec_for_distutils = lambda: None + + @classmethod + def pip_imported_during_build(cls): + """ + Detect if pip is being imported in a build script. Ref #2355. + """ + import traceback + + return any( + cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None) + ) + + @staticmethod + def frame_file_is_setup(frame): + """ + Return True if the indicated frame suggests a setup.py file. + """ + # some frames may not have __file__ (#2940) + return frame.f_globals.get('__file__', '').endswith('setup.py') + + def spec_for_sensitive_tests(self): + """ + Ensure stdlib distutils when running select tests under CPython. + + python/cpython#91169 + """ + clear_distutils() + self.spec_for_distutils = lambda: None + + sensitive_tests = ( + [ + 'test.test_distutils', + 'test.test_peg_generator', + 'test.test_importlib', + ] + if sys.version_info < (3, 10) + else [ + 'test.test_distutils', + ] + ) + + +for name in DistutilsMetaFinder.sensitive_tests: + setattr( + DistutilsMetaFinder, + f'spec_for_{name}', + DistutilsMetaFinder.spec_for_sensitive_tests, + ) + + +DISTUTILS_FINDER = DistutilsMetaFinder() + + +def add_shim(): + DISTUTILS_FINDER in sys.meta_path or insert_shim() + + +class shim: + def __enter__(self): + insert_shim() + + def __exit__(self, exc, value, tb): + remove_shim() + + +def insert_shim(): + sys.meta_path.insert(0, DISTUTILS_FINDER) + + +def remove_shim(): + try: + sys.meta_path.remove(DISTUTILS_FINDER) + except ValueError: + pass diff --git a/axios-example/lib/python3.10/site-packages/_distutils_hack/override.py b/axios-example/lib/python3.10/site-packages/_distutils_hack/override.py new file mode 100644 index 0000000..2cc433a --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/_distutils_hack/override.py @@ -0,0 +1 @@ +__import__('_distutils_hack').do_override() diff --git a/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/METADATA new file mode 100644 index 0000000..c028303 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/METADATA @@ -0,0 +1,145 @@ +Metadata-Version: 2.1 +Name: async-generator +Version: 1.10 +Summary: Async generators and context managers for Python 3.5+ +Home-page: https://github.com/python-trio/async_generator +Author: Nathaniel J. Smith +Author-email: njs@pobox.com +License: MIT -or- Apache License 2.0 +Keywords: async +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Framework :: AsyncIO +Requires-Python: >=3.5 + +.. image:: https://img.shields.io/badge/chat-join%20now-blue.svg + :target: https://gitter.im/python-trio/general + :alt: Join chatroom + +.. image:: https://img.shields.io/badge/docs-read%20now-blue.svg + :target: https://async-generator.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +.. image:: https://travis-ci.org/python-trio/async_generator.svg?branch=master + :target: https://travis-ci.org/python-trio/async_generator + :alt: Automated test status + +.. image:: https://ci.appveyor.com/api/projects/status/af4eyed8o8tc3t0r/branch/master?svg=true + :target: https://ci.appveyor.com/project/python-trio/trio/history + :alt: Automated test status (Windows) + +.. image:: https://codecov.io/gh/python-trio/async_generator/branch/master/graph/badge.svg + :target: https://codecov.io/gh/python-trio/async_generator + :alt: Test coverage + +The async_generator library +=========================== + +Python 3.6 added `async generators +`__. (What's an async +generator? `Check out my 5-minute lightning talk demo from PyCon 2016 +`__.) Python 3.7 adds some more +tools to make them usable, like ``contextlib.asynccontextmanager``. + +This library gives you all that back to Python 3.5. + +For example, this code only works in Python 3.6+: + +.. code-block:: python3 + + async def load_json_lines(stream_reader): + async for line in stream_reader: + yield json.loads(line) + +But this code does the same thing, and works on Python 3.5+: + +.. code-block:: python3 + + from async_generator import async_generator, yield_ + + @async_generator + async def load_json_lines(stream_reader): + async for line in stream_reader: + await yield_(json.loads(line)) + +Or in Python 3.7, you can write: + +.. code-block:: python3 + + from contextlib import asynccontextmanager + + @asynccontextmanager + async def background_server(): + async with trio.open_nursery() as nursery: + value = await nursery.start(my_server) + try: + yield value + finally: + # Kill the server when the scope exits + nursery.cancel_scope.cancel() + +This is the same, but back to 3.5: + +.. code-block:: python3 + + from async_generator import async_generator, yield_, asynccontextmanager + + @asynccontextmanager + @async_generator + async def background_server(): + async with trio.open_nursery() as nursery: + value = await nursery.start(my_server) + try: + await yield_(value) + finally: + # Kill the server when the scope exits + nursery.cancel_scope.cancel() + +(And if you're on 3.6, you can use ``@asynccontextmanager`` with +native generators.) + + +Let's do this +============= + +* Install: ``python3 -m pip install -U async_generator`` (or on Windows, + maybe ``py -3 -m pip install -U async_generator`` + +* Manual: https://async-generator.readthedocs.io/ + +* Bug tracker and source code: https://github.com/python-trio/async_generator + +* Real-time chat: https://gitter.im/python-trio/general + +* License: MIT or Apache 2, your choice + +* Contributor guide: https://trio.readthedocs.io/en/latest/contributing.html + +* Code of conduct: Contributors are requested to follow our `code of + conduct + `__ in + all project spaces. + + +How come some of those links talk about "trio"? +=============================================== + +`Trio `__ is a new async concurrency +library for Python that's obsessed with usability and correctness – we +want to make it *easy* to get things *right*. The ``async_generator`` +library is maintained by the Trio project as part of that mission, and +because Trio uses ``async_generator`` internally. + +You can use ``async_generator`` with any async library. It works great +with ``asyncio``, or Twisted, or whatever you like. (But we think Trio +is pretty sweet.) + + diff --git a/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/RECORD new file mode 100644 index 0000000..cc5c16f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/RECORD @@ -0,0 +1,21 @@ +async_generator-1.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +async_generator-1.10.dist-info/METADATA,sha256=FZoDYGYfSdJkSUSR5T_YMqq2TnwYa-RFOm6SbhWFzGA,4870 +async_generator-1.10.dist-info/RECORD,, +async_generator-1.10.dist-info/WHEEL,sha256=NzFAKnL7g-U64xnS1s5e3mJnxKpOTeOtlXdFwS9yNXI,92 +async_generator-1.10.dist-info/top_level.txt,sha256=Qc2NF6EJciFqrZ6gAdWuQIveMaqWJw4jqv1anjEHT_U,16 +async_generator/__init__.py,sha256=6eYc-CD3B5kQx8LzMhTEqJyKQH5UTsy8IZhR3AvcVb8,454 +async_generator/__pycache__/__init__.cpython-310.pyc,, +async_generator/__pycache__/_impl.cpython-310.pyc,, +async_generator/__pycache__/_util.cpython-310.pyc,, +async_generator/__pycache__/_version.cpython-310.pyc,, +async_generator/_impl.py,sha256=t1p5goS6TrQmpxLL4vOFa9zpl0SorICI8WZc8e81lxU,16106 +async_generator/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +async_generator/_tests/__pycache__/__init__.cpython-310.pyc,, +async_generator/_tests/__pycache__/conftest.cpython-310.pyc,, +async_generator/_tests/__pycache__/test_async_generator.cpython-310.pyc,, +async_generator/_tests/__pycache__/test_util.cpython-310.pyc,, +async_generator/_tests/conftest.py,sha256=eL5uA75o6d9feDTeEXu8vYDg-kgbnfuaGILJKGyWOFw,1211 +async_generator/_tests/test_async_generator.py,sha256=HBXQAlZdt68hzSQ6eMoSYsoO--Bic3Ojv1Z71hCQb7U,27936 +async_generator/_tests/test_util.py,sha256=-vLPOW_V2etk3Bf2M3cqEOGjxeRPFnSGfftsIYBaCCQ,6373 +async_generator/_util.py,sha256=jtBz2-fn6ec0JmaKKY-sC0TAq6zqGAKL3qs7LYQ4uFw,4358 +async_generator/_version.py,sha256=Nas37COFU-AbvlukCSCZDPrvCzgtKiG5QGZXnYenLC8,21 diff --git a/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/WHEEL new file mode 100644 index 0000000..bff023e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.31.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/top_level.txt new file mode 100644 index 0000000..9d6bff8 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator-1.10.dist-info/top_level.txt @@ -0,0 +1 @@ +async_generator diff --git a/axios-example/lib/python3.10/site-packages/async_generator/__init__.py b/axios-example/lib/python3.10/site-packages/async_generator/__init__.py new file mode 100644 index 0000000..e81a8fe --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/__init__.py @@ -0,0 +1,23 @@ +from ._version import __version__ +from ._impl import ( + async_generator, + yield_, + yield_from_, + isasyncgen, + isasyncgenfunction, + get_asyncgen_hooks, + set_asyncgen_hooks, +) +from ._util import aclosing, asynccontextmanager + +__all__ = [ + "async_generator", + "yield_", + "yield_from_", + "aclosing", + "isasyncgen", + "isasyncgenfunction", + "asynccontextmanager", + "get_asyncgen_hooks", + "set_asyncgen_hooks", +] diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_impl.py b/axios-example/lib/python3.10/site-packages/async_generator/_impl.py new file mode 100644 index 0000000..0b87421 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_impl.py @@ -0,0 +1,455 @@ +import sys +from functools import wraps +from types import coroutine +import inspect +from inspect import ( + getcoroutinestate, CORO_CREATED, CORO_CLOSED, CORO_SUSPENDED +) +import collections.abc + + +class YieldWrapper: + def __init__(self, payload): + self.payload = payload + + +def _wrap(value): + return YieldWrapper(value) + + +def _is_wrapped(box): + return isinstance(box, YieldWrapper) + + +def _unwrap(box): + return box.payload + + +# This is the magic code that lets you use yield_ and yield_from_ with native +# generators. +# +# The old version worked great on Linux and MacOS, but not on Windows, because +# it depended on _PyAsyncGenValueWrapperNew. The new version segfaults +# everywhere, and I'm not sure why -- probably my lack of understanding +# of ctypes and refcounts. +# +# There are also some commented out tests that should be re-enabled if this is +# fixed: +# +# if sys.version_info >= (3, 6): +# # Use the same box type that the interpreter uses internally. This allows +# # yield_ and (more importantly!) yield_from_ to work in built-in +# # generators. +# import ctypes # mua ha ha. +# +# # We used to call _PyAsyncGenValueWrapperNew to create and set up new +# # wrapper objects, but that symbol isn't available on Windows: +# # +# # https://github.com/python-trio/async_generator/issues/5 +# # +# # Fortunately, the type object is available, but it means we have to do +# # this the hard way. +# +# # We don't actually need to access this, but we need to make a ctypes +# # structure so we can call addressof. +# class _ctypes_PyTypeObject(ctypes.Structure): +# pass +# _PyAsyncGenWrappedValue_Type_ptr = ctypes.addressof( +# _ctypes_PyTypeObject.in_dll( +# ctypes.pythonapi, "_PyAsyncGenWrappedValue_Type")) +# _PyObject_GC_New = ctypes.pythonapi._PyObject_GC_New +# _PyObject_GC_New.restype = ctypes.py_object +# _PyObject_GC_New.argtypes = (ctypes.c_void_p,) +# +# _Py_IncRef = ctypes.pythonapi.Py_IncRef +# _Py_IncRef.restype = None +# _Py_IncRef.argtypes = (ctypes.py_object,) +# +# class _ctypes_PyAsyncGenWrappedValue(ctypes.Structure): +# _fields_ = [ +# ('PyObject_HEAD', ctypes.c_byte * object().__sizeof__()), +# ('agw_val', ctypes.py_object), +# ] +# def _wrap(value): +# box = _PyObject_GC_New(_PyAsyncGenWrappedValue_Type_ptr) +# raw = ctypes.cast(ctypes.c_void_p(id(box)), +# ctypes.POINTER(_ctypes_PyAsyncGenWrappedValue)) +# raw.contents.agw_val = value +# _Py_IncRef(value) +# return box +# +# def _unwrap(box): +# assert _is_wrapped(box) +# raw = ctypes.cast(ctypes.c_void_p(id(box)), +# ctypes.POINTER(_ctypes_PyAsyncGenWrappedValue)) +# value = raw.contents.agw_val +# _Py_IncRef(value) +# return value +# +# _PyAsyncGenWrappedValue_Type = type(_wrap(1)) +# def _is_wrapped(box): +# return isinstance(box, _PyAsyncGenWrappedValue_Type) + + +# The magic @coroutine decorator is how you write the bottom level of +# coroutine stacks -- 'async def' can only use 'await' = yield from; but +# eventually we must bottom out in a @coroutine that calls plain 'yield'. +@coroutine +def _yield_(value): + return (yield _wrap(value)) + + +# But we wrap the bare @coroutine version in an async def, because async def +# has the magic feature that users can get warnings messages if they forget to +# use 'await'. +async def yield_(value=None): + return await _yield_(value) + + +async def yield_from_(delegate): + # Transcribed with adaptations from: + # + # https://www.python.org/dev/peps/pep-0380/#formal-semantics + # + # This takes advantage of a sneaky trick: if an @async_generator-wrapped + # function calls another async function (like yield_from_), and that + # second async function calls yield_, then because of the hack we use to + # implement yield_, the yield_ will actually propagate through yield_from_ + # back to the @async_generator wrapper. So even though we're a regular + # function, we can directly yield values out of the calling async + # generator. + def unpack_StopAsyncIteration(e): + if e.args: + return e.args[0] + else: + return None + + _i = type(delegate).__aiter__(delegate) + if hasattr(_i, "__await__"): + _i = await _i + try: + _y = await type(_i).__anext__(_i) + except StopAsyncIteration as _e: + _r = unpack_StopAsyncIteration(_e) + else: + while 1: + try: + _s = await yield_(_y) + except GeneratorExit as _e: + try: + _m = _i.aclose + except AttributeError: + pass + else: + await _m() + raise _e + except BaseException as _e: + _x = sys.exc_info() + try: + _m = _i.athrow + except AttributeError: + raise _e + else: + try: + _y = await _m(*_x) + except StopAsyncIteration as _e: + _r = unpack_StopAsyncIteration(_e) + break + else: + try: + if _s is None: + _y = await type(_i).__anext__(_i) + else: + _y = await _i.asend(_s) + except StopAsyncIteration as _e: + _r = unpack_StopAsyncIteration(_e) + break + return _r + + +# This is the awaitable / iterator that implements asynciter.__anext__() and +# friends. +# +# Note: we can be sloppy about the distinction between +# +# type(self._it).__next__(self._it) +# +# and +# +# self._it.__next__() +# +# because we happen to know that self._it is not a general iterator object, +# but specifically a coroutine iterator object where these are equivalent. +class ANextIter: + def __init__(self, it, first_fn, *first_args): + self._it = it + self._first_fn = first_fn + self._first_args = first_args + + def __await__(self): + return self + + def __next__(self): + if self._first_fn is not None: + first_fn = self._first_fn + first_args = self._first_args + self._first_fn = self._first_args = None + return self._invoke(first_fn, *first_args) + else: + return self._invoke(self._it.__next__) + + def send(self, value): + return self._invoke(self._it.send, value) + + def throw(self, type, value=None, traceback=None): + return self._invoke(self._it.throw, type, value, traceback) + + def _invoke(self, fn, *args): + try: + result = fn(*args) + except StopIteration as e: + # The underlying generator returned, so we should signal the end + # of iteration. + raise StopAsyncIteration(e.value) + except StopAsyncIteration as e: + # PEP 479 says: if a generator raises Stop(Async)Iteration, then + # it should be wrapped into a RuntimeError. Python automatically + # enforces this for StopIteration; for StopAsyncIteration we need + # to it ourselves. + raise RuntimeError( + "async_generator raise StopAsyncIteration" + ) from e + if _is_wrapped(result): + raise StopIteration(_unwrap(result)) + else: + return result + + +UNSPECIFIED = object() +try: + from sys import get_asyncgen_hooks, set_asyncgen_hooks + +except ImportError: + import threading + + asyncgen_hooks = collections.namedtuple( + "asyncgen_hooks", ("firstiter", "finalizer") + ) + + class _hooks_storage(threading.local): + def __init__(self): + self.firstiter = None + self.finalizer = None + + _hooks = _hooks_storage() + + def get_asyncgen_hooks(): + return asyncgen_hooks( + firstiter=_hooks.firstiter, finalizer=_hooks.finalizer + ) + + def set_asyncgen_hooks(firstiter=UNSPECIFIED, finalizer=UNSPECIFIED): + if firstiter is not UNSPECIFIED: + if firstiter is None or callable(firstiter): + _hooks.firstiter = firstiter + else: + raise TypeError( + "callable firstiter expected, got {}".format( + type(firstiter).__name__ + ) + ) + + if finalizer is not UNSPECIFIED: + if finalizer is None or callable(finalizer): + _hooks.finalizer = finalizer + else: + raise TypeError( + "callable finalizer expected, got {}".format( + type(finalizer).__name__ + ) + ) + + +class AsyncGenerator: + # https://bitbucket.org/pypy/pypy/issues/2786: + # PyPy implements 'await' in a way that requires the frame object + # used to execute a coroutine to keep a weakref to that coroutine. + # During a GC pass, weakrefs to all doomed objects are broken + # before any of the doomed objects' finalizers are invoked. + # If an AsyncGenerator is unreachable, its _coroutine probably + # is too, and the weakref from ag._coroutine.cr_frame to + # ag._coroutine will be broken before ag.__del__ can do its + # one-turn close attempt or can schedule a full aclose() using + # the registered finalization hook. It doesn't look like the + # underlying issue is likely to be fully fixed anytime soon, + # so we work around it by preventing an AsyncGenerator and + # its _coroutine from being considered newly unreachable at + # the same time if the AsyncGenerator's finalizer might want + # to iterate the coroutine some more. + _pypy_issue2786_workaround = set() + + def __init__(self, coroutine): + self._coroutine = coroutine + self._it = coroutine.__await__() + self.ag_running = False + self._finalizer = None + self._closed = False + self._hooks_inited = False + + # On python 3.5.0 and 3.5.1, __aiter__ must be awaitable. + # Starting in 3.5.2, it should not be awaitable, and if it is, then it + # raises a PendingDeprecationWarning. + # See: + # https://www.python.org/dev/peps/pep-0492/#api-design-and-implementation-revisions + # https://docs.python.org/3/reference/datamodel.html#async-iterators + # https://bugs.python.org/issue27243 + if sys.version_info < (3, 5, 2): + + async def __aiter__(self): + return self + else: + + def __aiter__(self): + return self + + ################################################################ + # Introspection attributes + ################################################################ + + @property + def ag_code(self): + return self._coroutine.cr_code + + @property + def ag_frame(self): + return self._coroutine.cr_frame + + ################################################################ + # Core functionality + ################################################################ + + # These need to return awaitables, rather than being async functions, + # to match the native behavior where the firstiter hook is called + # immediately on asend()/etc, even if the coroutine that asend() + # produces isn't awaited for a bit. + + def __anext__(self): + return self._do_it(self._it.__next__) + + def asend(self, value): + return self._do_it(self._it.send, value) + + def athrow(self, type, value=None, traceback=None): + return self._do_it(self._it.throw, type, value, traceback) + + def _do_it(self, start_fn, *args): + if not self._hooks_inited: + self._hooks_inited = True + (firstiter, self._finalizer) = get_asyncgen_hooks() + if firstiter is not None: + firstiter(self) + if sys.implementation.name == "pypy": + self._pypy_issue2786_workaround.add(self._coroutine) + + # On CPython 3.5.2 (but not 3.5.0), coroutines get cranky if you try + # to iterate them after they're exhausted. Generators OTOH just raise + # StopIteration. We want to convert the one into the other, so we need + # to avoid iterating stopped coroutines. + if getcoroutinestate(self._coroutine) is CORO_CLOSED: + raise StopAsyncIteration() + + async def step(): + if self.ag_running: + raise ValueError("async generator already executing") + try: + self.ag_running = True + return await ANextIter(self._it, start_fn, *args) + except StopAsyncIteration: + self._pypy_issue2786_workaround.discard(self._coroutine) + raise + finally: + self.ag_running = False + + return step() + + ################################################################ + # Cleanup + ################################################################ + + async def aclose(self): + state = getcoroutinestate(self._coroutine) + if state is CORO_CLOSED or self._closed: + return + # Make sure that even if we raise "async_generator ignored + # GeneratorExit", and thus fail to exhaust the coroutine, + # __del__ doesn't complain again. + self._closed = True + if state is CORO_CREATED: + # Make sure that aclose() on an unstarted generator returns + # successfully and prevents future iteration. + self._it.close() + return + try: + await self.athrow(GeneratorExit) + except (GeneratorExit, StopAsyncIteration): + self._pypy_issue2786_workaround.discard(self._coroutine) + else: + raise RuntimeError("async_generator ignored GeneratorExit") + + def __del__(self): + self._pypy_issue2786_workaround.discard(self._coroutine) + if getcoroutinestate(self._coroutine) is CORO_CREATED: + # Never started, nothing to clean up, just suppress the "coroutine + # never awaited" message. + self._coroutine.close() + if getcoroutinestate(self._coroutine + ) is CORO_SUSPENDED and not self._closed: + if self._finalizer is not None: + self._finalizer(self) + else: + # Mimic the behavior of native generators on GC with no finalizer: + # throw in GeneratorExit, run for one turn, and complain if it didn't + # finish. + thrower = self.athrow(GeneratorExit) + try: + thrower.send(None) + except (GeneratorExit, StopAsyncIteration): + pass + except StopIteration: + raise RuntimeError("async_generator ignored GeneratorExit") + else: + raise RuntimeError( + "async_generator {!r} awaited during finalization; install " + "a finalization hook to support this, or wrap it in " + "'async with aclosing(...):'" + .format(self.ag_code.co_name) + ) + finally: + thrower.close() + + +if hasattr(collections.abc, "AsyncGenerator"): + collections.abc.AsyncGenerator.register(AsyncGenerator) + + +def async_generator(coroutine_maker): + @wraps(coroutine_maker) + def async_generator_maker(*args, **kwargs): + return AsyncGenerator(coroutine_maker(*args, **kwargs)) + + async_generator_maker._async_gen_function = id(async_generator_maker) + return async_generator_maker + + +def isasyncgen(obj): + if hasattr(inspect, "isasyncgen"): + if inspect.isasyncgen(obj): + return True + return isinstance(obj, AsyncGenerator) + + +def isasyncgenfunction(obj): + if hasattr(inspect, "isasyncgenfunction"): + if inspect.isasyncgenfunction(obj): + return True + return getattr(obj, "_async_gen_function", -1) == id(obj) diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_tests/__init__.py b/axios-example/lib/python3.10/site-packages/async_generator/_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_tests/conftest.py b/axios-example/lib/python3.10/site-packages/async_generator/_tests/conftest.py new file mode 100644 index 0000000..6c42d45 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_tests/conftest.py @@ -0,0 +1,36 @@ +import pytest +from functools import wraps, partial +import inspect +import types + + +@types.coroutine +def mock_sleep(): + yield "mock_sleep" + + +# Wrap any 'async def' tests so that they get automatically iterated. +# We used to use pytest-asyncio as a convenient way to do this, but nowadays +# pytest-asyncio uses us! In addition to it being generally bad for our test +# infrastructure to depend on the code-under-test, this totally messes up +# coverage info because depending on pytest's plugin load order, we might get +# imported before pytest-cov can be loaded and start gathering coverage. +@pytest.hookimpl(tryfirst=True) +def pytest_pyfunc_call(pyfuncitem): + if inspect.iscoroutinefunction(pyfuncitem.obj): + fn = pyfuncitem.obj + + @wraps(fn) + def wrapper(**kwargs): + coro = fn(**kwargs) + try: + while True: + value = coro.send(None) + if value != "mock_sleep": # pragma: no cover + raise RuntimeError( + "coroutine runner confused: {!r}".format(value) + ) + except StopIteration: + pass + + pyfuncitem.obj = wrapper diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_async_generator.py b/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_async_generator.py new file mode 100644 index 0000000..7463663 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_async_generator.py @@ -0,0 +1,1015 @@ +import pytest + +import types +import sys +import collections.abc +from functools import wraps +import gc + +from .conftest import mock_sleep +from .. import ( + async_generator, + yield_, + yield_from_, + isasyncgen, + isasyncgenfunction, + get_asyncgen_hooks, + set_asyncgen_hooks, +) + + +# like list(it) but works on async iterators +async def collect(ait): + items = [] + async for value in ait: + items.append(value) + return items + + +################################################################ +# +# Basic test +# +################################################################ + + +@async_generator +async def async_range(count): + for i in range(count): + print("Calling yield_({})".format(i)) + await yield_(i) + + +@async_generator +async def double(ait): + async for value in ait: + await yield_(value * 2) + await mock_sleep() + + +class HasAsyncGenMethod: + def __init__(self, factor): + self._factor = factor + + @async_generator + async def async_multiplied(self, ait): + async for value in ait: + await yield_(value * self._factor) + + +async def test_async_generator(): + assert await collect(async_range(10)) == list(range(10)) + assert (await collect(double(async_range(5))) == [0, 2, 4, 6, 8]) + + tripler = HasAsyncGenMethod(3) + assert ( + await + collect(tripler.async_multiplied(async_range(5))) == [0, 3, 6, 9, 12] + ) + + +@async_generator +async def agen_yield_no_arg(): + await yield_() + + +async def test_yield_no_arg(): + assert await collect(agen_yield_no_arg()) == [None] + + +################################################################ +# +# async_generators return value +# +################################################################ + + +@async_generator +async def async_gen_with_non_None_return(): + await yield_(1) + await yield_(2) + return "hi" + + +async def test_bad_return_value(): + gen = async_gen_with_non_None_return() + async for item in gen: # pragma: no branch + assert item == 1 + break + async for item in gen: # pragma: no branch + assert item == 2 + break + try: + await gen.__anext__() + except StopAsyncIteration as e: + assert e.args[0] == "hi" + + +################################################################ +# +# Exhausitve tests of the different ways to re-enter a coroutine. +# +# It used to be that re-entering via send/__next__ would work, but throw() +# immediately followed by an await yield_(...) wouldn't work, and the +# YieldWrapper object would propagate back out to the coroutine runner. +# +# Before I fixed this, the 'assert value is None' check below would fail +# (because of the YieldWrapper leaking out), and if you removed that +# assertion, then the code would appear to run successfully but the final list +# would just be [1, 3] instead of [1, 2, 3]. +# +################################################################ + + +class MyTestError(Exception): + pass + + +# This unconditionally raises a MyTestError exception, so from the outside +# it's equivalent to a simple 'raise MyTestError`. But, for this test to check +# the thing we want it to check, the point is that the exception must be +# thrown in from the coroutine runner -- this simulates something like an +# 'await sock.recv(...) -> TimeoutError'. +@types.coroutine +def hit_me(): + yield "hit me" + + +@types.coroutine +def number_me(): + assert (yield "number me") == 1 + + +@types.coroutine +def next_me(): + assert (yield "next me") is None + + +@async_generator +async def yield_after_different_entries(): + await yield_(1) + try: + await hit_me() + except MyTestError: + await yield_(2) + await number_me() + await yield_(3) + await next_me() + await yield_(4) + + +def hostile_coroutine_runner(coro): + coro_iter = coro.__await__() + value = None + while True: + try: + if value == "hit me": + value = coro_iter.throw(MyTestError()) + elif value == "number me": + value = coro_iter.send(1) + else: + assert value in (None, "next me") + value = coro_iter.__next__() + except StopIteration as exc: + return exc.value + + +def test_yield_different_entries(): + coro = collect(yield_after_different_entries()) + yielded = hostile_coroutine_runner(coro) + assert yielded == [1, 2, 3, 4] + + +async def test_reentrance_forbidden(): + @async_generator + async def recurse(): + async for obj in agen: # pragma: no branch + await yield_(obj) # pragma: no cover + + agen = recurse() + with pytest.raises(ValueError): + async for _ in agen: # pragma: no branch + pass # pragma: no cover + + +async def test_reentrance_forbidden_simultaneous_asends(): + @async_generator + async def f(): + await mock_sleep() + + ag = f() + sender1 = ag.asend(None) + sender2 = ag.asend(None) + assert sender1.send(None) == "mock_sleep" + with pytest.raises(ValueError): + sender2.send(None) + with pytest.raises(StopAsyncIteration): + sender1.send(None) + await ag.aclose() + + +# https://bugs.python.org/issue32526 +async def test_reentrance_forbidden_while_suspended_in_coroutine_runner(): + @async_generator + async def f(): + await mock_sleep() + await yield_("final yield") + + ag = f() + asend_coro = ag.asend(None) + fut = asend_coro.send(None) + assert fut == "mock_sleep" + # Now the async generator's frame is not executing, but a call to asend() + # *is* executing. Make sure that in this case, ag_running is True, and we + # can't start up another call to asend(). + assert ag.ag_running + with pytest.raises(ValueError): + await ag.asend(None) + # Clean up + with pytest.raises(StopIteration): + asend_coro.send(None) + with pytest.raises(StopAsyncIteration): + ag.asend(None).send(None) + + +################################################################ +# +# asend +# +################################################################ + + +@async_generator +async def asend_me(): + assert (await yield_(1)) == 2 + assert (await yield_(3)) == 4 + + +async def test_asend(): + aiter = asend_me() + assert (await aiter.__anext__()) == 1 + assert (await aiter.asend(2)) == 3 + with pytest.raises(StopAsyncIteration): + await aiter.asend(4) + + +################################################################ +# +# athrow +# +################################################################ + + +@async_generator +async def athrow_me(): + with pytest.raises(KeyError): + await yield_(1) + with pytest.raises(ValueError): + await yield_(2) + await yield_(3) + + +async def test_athrow(): + aiter = athrow_me() + assert (await aiter.__anext__()) == 1 + assert (await aiter.athrow(KeyError("oops"))) == 2 + assert (await aiter.athrow(ValueError("oops"))) == 3 + with pytest.raises(OSError): + await aiter.athrow(OSError("oops")) + + +################################################################ +# +# aclose +# +################################################################ + + +@async_generator +async def close_me_aiter(track): + try: + await yield_(1) + except GeneratorExit: + track[0] = "closed" + raise + else: # pragma: no cover + track[0] = "wtf" + + +async def test_aclose(): + track = [None] + aiter = close_me_aiter(track) + async for obj in aiter: # pragma: no branch + assert obj == 1 + break + assert track[0] is None + await aiter.aclose() + assert track[0] == "closed" + + +async def test_aclose_on_unstarted_generator(): + aiter = close_me_aiter([None]) + await aiter.aclose() + async for obj in aiter: + assert False # pragma: no cover + + +async def test_aclose_on_finished_generator(): + aiter = async_range(3) + async for obj in aiter: + pass # pragma: no cover + await aiter.aclose() + + +@async_generator +async def sync_yield_during_aclose(): + try: + await yield_(1) + finally: + await mock_sleep() + + +@async_generator +async def async_yield_during_aclose(): + try: + await yield_(1) + finally: + await yield_(2) + + +async def test_aclose_yielding(): + aiter = sync_yield_during_aclose() + assert (await aiter.__anext__()) == 1 + # Doesn't raise: + await aiter.aclose() + + aiter = async_yield_during_aclose() + assert (await aiter.__anext__()) == 1 + with pytest.raises(RuntimeError): + await aiter.aclose() + + +################################################################ +# +# yield from +# +################################################################ + + +@async_generator +async def async_range_twice(count): + await yield_from_(async_range(count)) + await yield_(None) + await yield_from_(async_range(count)) + + +if sys.version_info >= (3, 6): + exec( + """ +async def native_async_range(count): + for i in range(count): + yield i + +# XX uncomment if/when we re-enable the ctypes hacks: +# async def native_async_range_twice(count): +# # make sure yield_from_ works inside a native async generator +# await yield_from_(async_range(count)) +# yield None +# # make sure we can yield_from_ a native async generator +# await yield_from_(native_async_range(count)) + """ + ) + + +async def test_async_yield_from_(): + assert await collect(async_range_twice(3)) == [ + 0, + 1, + 2, + None, + 0, + 1, + 2, + ] + + if sys.version_info >= (3, 6): + # Make sure we can yield_from_ a native generator + @async_generator + async def yield_from_native(): + await yield_from_(native_async_range(3)) + + assert await collect(yield_from_native()) == [0, 1, 2] + + # XX uncomment if/when we re-enable the ctypes hacks: + # if sys.version_info >= (3, 6): + # assert await collect(native_async_range_twice(3)) == [ + # 0, 1, 2, None, 0, 1, 2, + # ] + + +@async_generator +async def doubles_sends(value): + while True: + value = await yield_(2 * value) + + +@async_generator +async def wraps_doubles_sends(value): + await yield_from_(doubles_sends(value)) + + +async def test_async_yield_from_asend(): + gen = wraps_doubles_sends(10) + await gen.__anext__() == 20 + assert (await gen.asend(2)) == 4 + assert (await gen.asend(5)) == 10 + assert (await gen.asend(0)) == 0 + await gen.aclose() + + +async def test_async_yield_from_athrow(): + gen = async_range_twice(2) + assert (await gen.__anext__()) == 0 + with pytest.raises(ValueError): + await gen.athrow(ValueError) + + +@async_generator +async def returns_1(): + await yield_(0) + return 1 + + +@async_generator +async def yields_from_returns_1(): + await yield_(await yield_from_(returns_1())) + + +async def test_async_yield_from_return_value(): + assert await collect(yields_from_returns_1()) == [0, 1] + + +# Special cases to get coverage +async def test_yield_from_empty(): + @async_generator + async def empty(): + return "done" + + @async_generator + async def yield_from_empty(): + assert (await yield_from_(empty())) == "done" + + assert await collect(yield_from_empty()) == [] + + +async def test_yield_from_non_generator(): + class Countdown: + def __init__(self, count): + self.count = count + self.closed = False + + if sys.version_info < (3, 5, 2): + + async def __aiter__(self): + return self + else: + + def __aiter__(self): + return self + + async def __anext__(self): + self.count -= 1 + if self.count < 0: + raise StopAsyncIteration("boom") + return self.count + + async def aclose(self): + self.closed = True + + @async_generator + async def yield_from_countdown(count, happenings): + try: + c = Countdown(count) + assert (await yield_from_(c)) == "boom" + except BaseException as e: + if c.closed: + happenings.append("countdown closed") + happenings.append("raise") + return e + + h = [] + assert await collect(yield_from_countdown(3, h)) == [2, 1, 0] + assert h == [] + + # Throwing into a yield_from_(object with no athrow) just raises the + # exception in the generator. + h = [] + agen = yield_from_countdown(3, h) + assert await agen.__anext__() == 2 + exc = ValueError("x") + try: + await agen.athrow(exc) + except StopAsyncIteration as e: + assert e.args[0] is exc + assert h == ["raise"] + + # Calling aclose on the generator calls aclose on the iterator + h = [] + agen = yield_from_countdown(3, h) + assert await agen.__anext__() == 2 + await agen.aclose() + assert h == ["countdown closed", "raise"] + + # Throwing GeneratorExit into the generator calls *aclose* on the iterator + # (!) + h = [] + agen = yield_from_countdown(3, h) + assert await agen.__anext__() == 2 + exc = GeneratorExit() + with pytest.raises(StopAsyncIteration): + await agen.athrow(exc) + assert h == ["countdown closed", "raise"] + + +async def test_yield_from_non_generator_with_no_aclose(): + class Countdown: + def __init__(self, count): + self.count = count + self.closed = False + + if sys.version_info < (3, 5, 2): + + async def __aiter__(self): + return self + else: + + def __aiter__(self): + return self + + async def __anext__(self): + self.count -= 1 + if self.count < 0: + raise StopAsyncIteration("boom") + return self.count + + @async_generator + async def yield_from_countdown(count): + return await yield_from_(Countdown(count)) + + assert await collect(yield_from_countdown(3)) == [2, 1, 0] + + agen = yield_from_countdown(3) + assert await agen.__anext__() == 2 + assert await agen.__anext__() == 1 + # It's OK that Countdown has no aclose + await agen.aclose() + + +async def test_yield_from_with_old_style_aiter(): + # old-style 'async def __aiter__' should still work even on newer pythons + class Countdown: + def __init__(self, count): + self.count = count + self.closed = False + + # This is wrong, that's the point + async def __aiter__(self): + return self + + async def __anext__(self): + self.count -= 1 + if self.count < 0: + raise StopAsyncIteration("boom") + return self.count + + @async_generator + async def yield_from_countdown(count): + return await yield_from_(Countdown(count)) + + assert await collect(yield_from_countdown(3)) == [2, 1, 0] + + +async def test_yield_from_athrow_raises_StopAsyncIteration(): + @async_generator + async def catch(): + try: + while True: + await yield_("hi") + except Exception as exc: + return ("bye", exc) + + @async_generator + async def yield_from_catch(): + return await yield_from_(catch()) + + agen = yield_from_catch() + assert await agen.__anext__() == "hi" + assert await agen.__anext__() == "hi" + thrown = ValueError("oops") + try: + print(await agen.athrow(thrown)) + except StopAsyncIteration as caught: + assert caught.args == (("bye", thrown),) + else: + raise AssertionError # pragma: no cover + + +################################################################ +# __del__ +################################################################ + + +async def test___del__(capfd): + completions = 0 + + @async_generator + async def awaits_when_unwinding(): + await yield_(0) + try: + await yield_(1) + finally: + await mock_sleep() + try: + await yield_(2) + finally: + nonlocal completions + completions += 1 + + gen = awaits_when_unwinding() + # Hasn't started yet, so no problem + gen.__del__() + + gen = awaits_when_unwinding() + assert await collect(gen) == [0, 1, 2] + # Exhausted, so no problem + gen.__del__() + + for stop_after_turn in (1, 2, 3): + gen = awaits_when_unwinding() + for turn in range(stop_after_turn): + assert await gen.__anext__() == turn + await gen.aclose() + # Closed, so no problem + gen.__del__() + + for stop_after_turn in (1, 2, 3): + gen = awaits_when_unwinding() + for turn in range(stop_after_turn): + assert await gen.__anext__() == turn + + if stop_after_turn == 2: + # Stopped in the middle of a try/finally that awaits in the finally, + # so __del__ can't cleanup. + with pytest.raises(RuntimeError) as info: + gen.__del__() + assert "awaited during finalization; install a finalization hook" in str( + info.value + ) + else: + # Can clean up without awaiting, so __del__ is fine + gen.__del__() + + assert completions == 3 + + @async_generator + async def yields_when_unwinding(): + try: + await yield_(1) + finally: + await yield_(2) + + gen = yields_when_unwinding() + assert await gen.__anext__() == 1 + with pytest.raises(RuntimeError) as info: + gen.__del__() + + +################################################################ +# introspection +################################################################ + + +def test_isasyncgen(): + assert not isasyncgen(async_range) + assert isasyncgen(async_range(10)) + + if sys.version_info >= (3, 6): + assert not isasyncgen(native_async_range) + assert isasyncgen(native_async_range(10)) + + +def test_isasyncgenfunction(): + assert isasyncgenfunction(async_range) + assert not isasyncgenfunction(list) + assert not isasyncgenfunction(async_range(10)) + + if sys.version_info >= (3, 6): + assert isasyncgenfunction(native_async_range) + assert not isasyncgenfunction(native_async_range(10)) + + +# Very subtle bug: functools.wraps copies across the entire contents of the +# wrapped function's __dict__. We used to use a simple _is_async_gen=True +# attribute to mark async generators. But if we do that, then simple wrappers +# like async_range_wrapper *do* return True for isasyncgenfunction. But that's +# not how inspect.isasyncgenfunction works, and it also caused problems for +# sphinxcontrib-trio, because given a function like: +# +# @acontextmanager +# @async_generator +# async def async_cm(): +# ... +# +# then we end up with async_cm introspecting as both an async context manager +# and an async generator, and it doesn't know who to believe. With the +# correct, inspect.isasyncgenfunction-compliant behavior, we have async_cm +# introspecting as an async context manager, and async_cm.__wrapped__ +# introspecting as an async generator. +def test_isasyncgenfunction_is_not_inherited_by_wrappers(): + @wraps(async_range) + def async_range_wrapper(*args, **kwargs): # pragma: no cover + return async_range(*args, **kwargs) + + assert not isasyncgenfunction(async_range_wrapper) + assert isasyncgenfunction(async_range_wrapper.__wrapped__) + + +def test_collections_abc_AsyncGenerator(): + if hasattr(collections.abc, "AsyncGenerator"): + assert isinstance(async_range(10), collections.abc.AsyncGenerator) + + +async def test_ag_attributes(): + @async_generator + async def f(): + x = 1 + await yield_() + + agen = f() + assert agen.ag_code.co_name == "f" + async for _ in agen: # pragma: no branch + assert agen.ag_frame.f_locals["x"] == 1 + break + + +################################################################ +# Finicky tests to check that the overly clever ctype stuff has plausible +# refcounting + +from .. import _impl + + +@pytest.mark.skipif(not hasattr(sys, "getrefcount"), reason="CPython only") +def test_refcnt(): + x = object() + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + base_count = sys.getrefcount(x) + l = [_impl._wrap(x) for _ in range(100)] + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + assert sys.getrefcount(x) >= base_count + 100 + l2 = [_impl._unwrap(box) for box in l] + assert sys.getrefcount(x) >= base_count + 200 + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + del l + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + del l2 + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + print(sys.getrefcount(x)) + assert sys.getrefcount(x) == base_count + print(sys.getrefcount(x)) + + +################################################################ +# +# Edge cases +# +################################################################ + + +# PEP 479: StopIteration or StopAsyncIteration exiting from inside an async +# generator should produce a RuntimeError with the __cause__ set to the +# original exception. Note that contextlib.asynccontextmanager depends on this +# behavior. +@async_generator +async def lets_exception_out(): + await yield_() + + +async def test_throw_StopIteration_or_StopAsyncIteration(): + for cls in [StopIteration, StopAsyncIteration]: + agen = lets_exception_out() + await agen.asend(None) + exc = cls() + with pytest.raises(RuntimeError) as excinfo: + await agen.athrow(exc) + assert excinfo.type is RuntimeError + assert excinfo.value.__cause__ is exc + + +# No "coroutine was never awaited" warnings for async generators that are not +# iterated +async def test_no_spurious_unawaited_coroutine_warning(recwarn): + agen = async_range(10) + del agen + + # Run collection a few times to make sure any + # loops/resurrection/etc. stuff gets fully handled (necessary on pypy) + for _ in range(4): + gc.collect() + + # I've seen DeprecationWarnings here triggered by pytest-asyncio, so let's + # filter for RuntimeWarning. But if there are no warnings at all, then + # that's OK too, so tell coverage not to worry about it. + for msg in recwarn: # pragma: no cover + print(msg) + assert not issubclass(msg.category, RuntimeWarning) + + +################################################################ +# +# GC hooks +# +################################################################ + + +@pytest.fixture +def local_asyncgen_hooks(): + old_hooks = get_asyncgen_hooks() + yield + set_asyncgen_hooks(*old_hooks) + + +def test_gc_hooks_interface(local_asyncgen_hooks): + def one(agen): # pragma: no cover + pass + + def two(agen): # pragma: no cover + pass + + set_asyncgen_hooks(None, None) + assert get_asyncgen_hooks() == (None, None) + set_asyncgen_hooks(finalizer=two) + assert get_asyncgen_hooks() == (None, two) + set_asyncgen_hooks(firstiter=one) + assert get_asyncgen_hooks() == (one, two) + set_asyncgen_hooks(finalizer=None, firstiter=two) + assert get_asyncgen_hooks() == (two, None) + set_asyncgen_hooks(None, one) + assert get_asyncgen_hooks() == (None, one) + tup = (one, two) + set_asyncgen_hooks(*tup) + assert get_asyncgen_hooks() == tup + + with pytest.raises(TypeError): + set_asyncgen_hooks(firstiter=42) + + with pytest.raises(TypeError): + set_asyncgen_hooks(finalizer=False) + + def in_thread(results): + results.append(get_asyncgen_hooks()) + set_asyncgen_hooks(two, one) + results.append(get_asyncgen_hooks()) + + from threading import Thread + results = [] + thread = Thread(target=in_thread, args=(results,)) + thread.start() + thread.join() + assert results == [(None, None), (two, one)] + assert get_asyncgen_hooks() == (one, two) + + +async def test_gc_hooks_behavior(local_asyncgen_hooks): + events = [] + to_finalize = [] + + def firstiter(agen): + events.append("firstiter {}".format(agen.ag_frame.f_locals["ident"])) + + def finalizer(agen): + events.append("finalizer {}".format(agen.ag_frame.f_locals["ident"])) + to_finalize.append(agen) + + @async_generator + async def agen(ident): + events.append("yield 1 {}".format(ident)) + await yield_(1) + try: + events.append("yield 2 {}".format(ident)) + await yield_(2) + events.append("after yield 2 {}".format(ident)) + finally: + events.append("mock_sleep {}".format(ident)) + await mock_sleep() + try: + events.append("yield 3 {}".format(ident)) + await yield_(3) + finally: + events.append("unwind 3 {}".format(ident)) + # this one is included to make sure we _don't_ execute it + events.append("done {}".format(ident)) # pragma: no cover + + async def anext_verbosely(iter, ident): + events.append("before asend {}".format(ident)) + sender = iter.asend(None) + events.append("before send {}".format(ident)) + await sender + events.append("after asend {}".format(ident)) + + # Ensure that firstiter is called immediately on asend(), + # before the first turn of the coroutine that asend() returns, + # to match the behavior of native generators. + # Ensure that the firstiter that gets used is the one in effect + # at the time of that first call, rather than at the time of iteration. + iterA = agen("A") + iterB = agen("B") + await anext_verbosely(iterA, "A") + set_asyncgen_hooks(firstiter, finalizer) + await anext_verbosely(iterB, "B") + iterC = agen("C") + await anext_verbosely(iterC, "C") + + assert events == [ + "before asend A", "before send A", "yield 1 A", "after asend A", + "before asend B", "firstiter B", "before send B", "yield 1 B", + "after asend B", "before asend C", "firstiter C", "before send C", + "yield 1 C", "after asend C" + ] + del events[:] + + # Ensure that firstiter is only called once, even if we create + # two asend() coroutines before iterating either of them. + iterX = agen("X") + sender1 = iterX.asend(None) + sender2 = iterX.asend(None) + events.append("before close") + sender1.close() + sender2.close() + await iterX.aclose() + assert events == ["firstiter X", "before close"] + del events[:] + + from weakref import ref + refA, refB, refC = map(ref, (iterA, iterB, iterC)) + + # iterA uses the finalizer that was in effect when it started, i.e. no finalizer + await iterA.__anext__() + await iterA.__anext__() + del iterA + # Do multiple GC passes since we're deliberately shielding the + # coroutine objects from the first pass due to PyPy issue 2786. + for _ in range(4): + gc.collect() + assert refA() is None + assert events == [ + "yield 2 A", "after yield 2 A", "mock_sleep A", "yield 3 A", + "unwind 3 A" + ] + assert not to_finalize + del events[:] + + # iterB and iterC do use our finalizer + await iterC.__anext__() + await iterB.__anext__() + await iterC.__anext__() + idB, idC = id(iterB), id(iterC) + del iterB + for _ in range(4): + gc.collect() + del iterC + for _ in range(4): + gc.collect() + assert events == [ + "yield 2 C", "yield 2 B", "after yield 2 C", "mock_sleep C", + "yield 3 C", "finalizer B", "finalizer C" + ] + del events[:] + + # finalizer invokes aclose() is not called again once the revived reference drops + assert list(map(id, to_finalize)) == [idB, idC] + events.append("before aclose B") + await to_finalize[0].aclose() + events.append("before aclose C") + await to_finalize[1].aclose() + events.append("after aclose both") + del to_finalize[:] + for _ in range(4): + gc.collect() + assert refB() is None and refC() is None + + assert events == [ + "before aclose B", "mock_sleep B", "before aclose C", "unwind 3 C", + "after aclose both" + ] diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_util.py b/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_util.py new file mode 100644 index 0000000..16961d1 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_tests/test_util.py @@ -0,0 +1,227 @@ +import pytest + +from .. import aclosing, async_generator, yield_, asynccontextmanager + + +@async_generator +async def async_range(count, closed_slot): + try: + for i in range(count): # pragma: no branch + await yield_(i) + except GeneratorExit: + closed_slot[0] = True + + +async def test_aclosing(): + closed_slot = [False] + async with aclosing(async_range(10, closed_slot)) as gen: + it = iter(range(10)) + async for item in gen: # pragma: no branch + assert item == next(it) + if item == 4: + break + assert closed_slot[0] + + closed_slot = [False] + try: + async with aclosing(async_range(10, closed_slot)) as gen: + it = iter(range(10)) + async for item in gen: # pragma: no branch + assert item == next(it) + if item == 4: + raise ValueError() + except ValueError: + pass + assert closed_slot[0] + + +async def test_contextmanager_do_not_unchain_non_stopiteration_exceptions(): + @asynccontextmanager + @async_generator + async def manager_issue29692(): + try: + await yield_() + except Exception as exc: + raise RuntimeError('issue29692:Chained') from exc + + with pytest.raises(RuntimeError) as excinfo: + async with manager_issue29692(): + raise ZeroDivisionError + assert excinfo.value.args[0] == 'issue29692:Chained' + assert isinstance(excinfo.value.__cause__, ZeroDivisionError) + + # This is a little funky because of implementation details in + # async_generator It can all go away once we stop supporting Python3.5 + with pytest.raises(RuntimeError) as excinfo: + async with manager_issue29692(): + exc = StopIteration('issue29692:Unchained') + raise exc + assert excinfo.value.args[0] == 'issue29692:Chained' + cause = excinfo.value.__cause__ + assert cause.args[0] == 'generator raised StopIteration' + assert cause.__cause__ is exc + + with pytest.raises(StopAsyncIteration) as excinfo: + async with manager_issue29692(): + raise StopAsyncIteration('issue29692:Unchained') + assert excinfo.value.args[0] == 'issue29692:Unchained' + assert excinfo.value.__cause__ is None + + @asynccontextmanager + @async_generator + async def noop_async_context_manager(): + await yield_() + + with pytest.raises(StopIteration): + async with noop_async_context_manager(): + raise StopIteration + + +# Native async generators are only available from Python 3.6 and onwards +nativeasyncgenerators = True +try: + exec( + """ +@asynccontextmanager +async def manager_issue29692_2(): + try: + yield + except Exception as exc: + raise RuntimeError('issue29692:Chained') from exc +""" + ) +except SyntaxError: + nativeasyncgenerators = False + + +@pytest.mark.skipif( + not nativeasyncgenerators, + reason="Python < 3.6 doesn't have native async generators" +) +async def test_native_contextmanager_do_not_unchain_non_stopiteration_exceptions( +): + + with pytest.raises(RuntimeError) as excinfo: + async with manager_issue29692_2(): + raise ZeroDivisionError + assert excinfo.value.args[0] == 'issue29692:Chained' + assert isinstance(excinfo.value.__cause__, ZeroDivisionError) + + for cls in [StopIteration, StopAsyncIteration]: + with pytest.raises(cls) as excinfo: + async with manager_issue29692_2(): + raise cls('issue29692:Unchained') + assert excinfo.value.args[0] == 'issue29692:Unchained' + assert excinfo.value.__cause__ is None + + +async def test_asynccontextmanager_exception_passthrough(): + # This was the cause of annoying coverage flapping, see gh-140 + @asynccontextmanager + @async_generator + async def noop_async_context_manager(): + await yield_() + + for exc_type in [StopAsyncIteration, RuntimeError, ValueError]: + with pytest.raises(exc_type): + async with noop_async_context_manager(): + raise exc_type + + # And let's also check a boring nothing pass-through while we're at it + async with noop_async_context_manager(): + pass + + +async def test_asynccontextmanager_catches_exception(): + @asynccontextmanager + @async_generator + async def catch_it(): + with pytest.raises(ValueError): + await yield_() + + async with catch_it(): + raise ValueError + + +async def test_asynccontextmanager_different_exception(): + @asynccontextmanager + @async_generator + async def switch_it(): + try: + await yield_() + except KeyError: + raise ValueError + + with pytest.raises(ValueError): + async with switch_it(): + raise KeyError + + +async def test_asynccontextmanager_nice_message_on_sync_enter(): + @asynccontextmanager + @async_generator + async def xxx(): # pragma: no cover + await yield_() + + cm = xxx() + + with pytest.raises(RuntimeError) as excinfo: + with cm: + pass # pragma: no cover + + assert "async with" in str(excinfo.value) + + async with cm: + pass + + +async def test_asynccontextmanager_no_yield(): + @asynccontextmanager + @async_generator + async def yeehaw(): + pass + + with pytest.raises(RuntimeError) as excinfo: + async with yeehaw(): + assert False # pragma: no cover + + assert "didn't yield" in str(excinfo.value) + + +async def test_asynccontextmanager_too_many_yields(): + closed_count = 0 + + @asynccontextmanager + @async_generator + async def doubleyield(): + try: + await yield_() + except Exception: + pass + try: + await yield_() + finally: + nonlocal closed_count + closed_count += 1 + + with pytest.raises(RuntimeError) as excinfo: + async with doubleyield(): + pass + + assert "didn't stop" in str(excinfo.value) + assert closed_count == 1 + + with pytest.raises(RuntimeError) as excinfo: + async with doubleyield(): + raise ValueError + + assert "didn't stop after athrow" in str(excinfo.value) + assert closed_count == 2 + + +async def test_asynccontextmanager_requires_asyncgenfunction(): + with pytest.raises(TypeError): + + @asynccontextmanager + def syncgen(): # pragma: no cover + yield diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_util.py b/axios-example/lib/python3.10/site-packages/async_generator/_util.py new file mode 100644 index 0000000..aa6f113 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_util.py @@ -0,0 +1,110 @@ +import sys +from functools import wraps +from ._impl import isasyncgenfunction + + +class aclosing: + def __init__(self, aiter): + self._aiter = aiter + + async def __aenter__(self): + return self._aiter + + async def __aexit__(self, *args): + await self._aiter.aclose() + + +# Very much derived from the one in contextlib, by copy/pasting and then +# asyncifying everything. (Also I dropped the obscure support for using +# context managers as function decorators. It could be re-added; I just +# couldn't be bothered.) +# So this is a derivative work licensed under the PSF License, which requires +# the following notice: +# +# Copyright © 2001-2017 Python Software Foundation; All Rights Reserved +class _AsyncGeneratorContextManager: + def __init__(self, func, args, kwds): + self._func_name = func.__name__ + self._agen = func(*args, **kwds).__aiter__() + + async def __aenter__(self): + if sys.version_info < (3, 5, 2): + self._agen = await self._agen + try: + return await self._agen.asend(None) + except StopAsyncIteration: + raise RuntimeError("async generator didn't yield") from None + + async def __aexit__(self, type, value, traceback): + async with aclosing(self._agen): + if type is None: + try: + await self._agen.asend(None) + except StopAsyncIteration: + return False + else: + raise RuntimeError("async generator didn't stop") + else: + # It used to be possible to have type != None, value == None: + # https://bugs.python.org/issue1705170 + # but AFAICT this can't happen anymore. + assert value is not None + try: + await self._agen.athrow(type, value, traceback) + raise RuntimeError( + "async generator didn't stop after athrow()" + ) + except StopAsyncIteration as exc: + # Suppress StopIteration *unless* it's the same exception + # that was passed to throw(). This prevents a + # StopIteration raised inside the "with" statement from + # being suppressed. + return (exc is not value) + except RuntimeError as exc: + # Don't re-raise the passed in exception. (issue27112) + if exc is value: + return False + # Likewise, avoid suppressing if a StopIteration exception + # was passed to throw() and later wrapped into a + # RuntimeError (see PEP 479). + if (isinstance(value, (StopIteration, StopAsyncIteration)) + and exc.__cause__ is value): + return False + raise + except: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise an + # exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so + # this fixes the impedance mismatch between the throw() + # protocol and the __exit__() protocol. + # + if sys.exc_info()[1] is value: + return False + raise + + def __enter__(self): + raise RuntimeError( + "use 'async with {func_name}(...)', not 'with {func_name}(...)'". + format(func_name=self._func_name) + ) + + def __exit__(self): # pragma: no cover + assert False, """Never called, but should be defined""" + + +def asynccontextmanager(func): + """Like @contextmanager, but async.""" + if not isasyncgenfunction(func): + raise TypeError( + "must be an async generator (native or from async_generator; " + "if using @async_generator then @acontextmanager must be on top." + ) + + @wraps(func) + def helper(*args, **kwds): + return _AsyncGeneratorContextManager(func, args, kwds) + + # A hint for sphinxcontrib-trio: + helper.__returns_acontextmanager__ = True + return helper diff --git a/axios-example/lib/python3.10/site-packages/async_generator/_version.py b/axios-example/lib/python3.10/site-packages/async_generator/_version.py new file mode 100644 index 0000000..bb438da --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/async_generator/_version.py @@ -0,0 +1 @@ +__version__ = "1.10" diff --git a/axios-example/lib/python3.10/site-packages/attr/__init__.py b/axios-example/lib/python3.10/site-packages/attr/__init__.py new file mode 100644 index 0000000..386305d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/__init__.py @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: MIT + + +import sys + +from functools import partial + +from . import converters, exceptions, filters, setters, validators +from ._cmp import cmp_using +from ._config import get_run_validators, set_run_validators +from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types +from ._make import ( + NOTHING, + Attribute, + Factory, + attrib, + attrs, + fields, + fields_dict, + make_class, + validate, +) +from ._version_info import VersionInfo + + +__version__ = "22.1.0" +__version_info__ = VersionInfo._from_version_string(__version__) + +__title__ = "attrs" +__description__ = "Classes Without Boilerplate" +__url__ = "https://www.attrs.org/" +__uri__ = __url__ +__doc__ = __description__ + " <" + __uri__ + ">" + +__author__ = "Hynek Schlawack" +__email__ = "hs@ox.cx" + +__license__ = "MIT" +__copyright__ = "Copyright (c) 2015 Hynek Schlawack" + + +s = attributes = attrs +ib = attr = attrib +dataclass = partial(attrs, auto_attribs=True) # happy Easter ;) + +__all__ = [ + "Attribute", + "Factory", + "NOTHING", + "asdict", + "assoc", + "astuple", + "attr", + "attrib", + "attributes", + "attrs", + "cmp_using", + "converters", + "evolve", + "exceptions", + "fields", + "fields_dict", + "filters", + "get_run_validators", + "has", + "ib", + "make_class", + "resolve_types", + "s", + "set_run_validators", + "setters", + "validate", + "validators", +] + +if sys.version_info[:2] >= (3, 6): + from ._next_gen import define, field, frozen, mutable # noqa: F401 + + __all__.extend(("define", "field", "frozen", "mutable")) diff --git a/axios-example/lib/python3.10/site-packages/attr/__init__.pyi b/axios-example/lib/python3.10/site-packages/attr/__init__.pyi new file mode 100644 index 0000000..03cc4c8 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/__init__.pyi @@ -0,0 +1,486 @@ +import sys + +from typing import ( + Any, + Callable, + ClassVar, + Dict, + Generic, + List, + Mapping, + Optional, + Protocol, + Sequence, + Tuple, + Type, + TypeVar, + Union, + overload, +) + +# `import X as X` is required to make these public +from . import converters as converters +from . import exceptions as exceptions +from . import filters as filters +from . import setters as setters +from . import validators as validators +from ._cmp import cmp_using as cmp_using +from ._version_info import VersionInfo + +__version__: str +__version_info__: VersionInfo +__title__: str +__description__: str +__url__: str +__uri__: str +__author__: str +__email__: str +__license__: str +__copyright__: str + +_T = TypeVar("_T") +_C = TypeVar("_C", bound=type) + +_EqOrderType = Union[bool, Callable[[Any], Any]] +_ValidatorType = Callable[[Any, Attribute[_T], _T], Any] +_ConverterType = Callable[[Any], Any] +_FilterType = Callable[[Attribute[_T], _T], bool] +_ReprType = Callable[[Any], str] +_ReprArgType = Union[bool, _ReprType] +_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any] +_OnSetAttrArgType = Union[ + _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType +] +_FieldTransformer = Callable[ + [type, List[Attribute[Any]]], List[Attribute[Any]] +] +# FIXME: in reality, if multiple validators are passed they must be in a list +# or tuple, but those are invariant and so would prevent subtypes of +# _ValidatorType from working when passed in a list or tuple. +_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] + +# A protocol to be able to statically accept an attrs class. +class AttrsInstance(Protocol): + __attrs_attrs__: ClassVar[Any] + +# _make -- + +NOTHING: object + +# NOTE: Factory lies about its return type to make this possible: +# `x: List[int] # = Factory(list)` +# Work around mypy issue #4554 in the common case by using an overload. +if sys.version_info >= (3, 8): + from typing import Literal + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Callable[[Any], _T], + takes_self: Literal[True], + ) -> _T: ... + @overload + def Factory( + factory: Callable[[], _T], + takes_self: Literal[False], + ) -> _T: ... + +else: + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Union[Callable[[Any], _T], Callable[[], _T]], + takes_self: bool = ..., + ) -> _T: ... + +# Static type inference support via __dataclass_transform__ implemented as per: +# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md +# This annotation must be applied to all overloads of "define" and "attrs" +# +# NOTE: This is a typing construct and does not exist at runtime. Extensions +# wrapping attrs decorators should declare a separate __dataclass_transform__ +# signature in the extension module using the specification linked above to +# provide pyright support. +def __dataclass_transform__( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_default: bool = False, + field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()), +) -> Callable[[_T], _T]: ... + +class Attribute(Generic[_T]): + name: str + default: Optional[_T] + validator: Optional[_ValidatorType[_T]] + repr: _ReprArgType + cmp: _EqOrderType + eq: _EqOrderType + order: _EqOrderType + hash: Optional[bool] + init: bool + converter: Optional[_ConverterType] + metadata: Dict[Any, Any] + type: Optional[Type[_T]] + kw_only: bool + on_setattr: _OnSetAttrType + def evolve(self, **changes: Any) -> "Attribute[Any]": ... + +# NOTE: We had several choices for the annotation to use for type arg: +# 1) Type[_T] +# - Pros: Handles simple cases correctly +# - Cons: Might produce less informative errors in the case of conflicting +# TypeVars e.g. `attr.ib(default='bad', type=int)` +# 2) Callable[..., _T] +# - Pros: Better error messages than #1 for conflicting TypeVars +# - Cons: Terrible error messages for validator checks. +# e.g. attr.ib(type=int, validator=validate_str) +# -> error: Cannot infer function type argument +# 3) type (and do all of the work in the mypy plugin) +# - Pros: Simple here, and we could customize the plugin with our own errors. +# - Cons: Would need to write mypy plugin code to handle all the cases. +# We chose option #1. + +# `attr` lies about its return type to make the following possible: +# attr() -> Any +# attr(8) -> int +# attr(validator=) -> Whatever the callable expects. +# This makes this type of assignments possible: +# x: int = attr(8) +# +# This form catches explicit None or no default but with no other arguments +# returns Any. +@overload +def attrib( + default: None = ..., + validator: None = ..., + repr: _ReprArgType = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: None = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def attrib( + default: None = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def attrib( + default: _T, + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def attrib( + default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: object = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... +@overload +def field( + *, + default: None = ..., + validator: None = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def field( + *, + default: None = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def field( + *, + default: _T, + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def field( + *, + default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... +@overload +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) +def attrs( + maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + auto_detect: bool = ..., + collect_by_mro: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., +) -> _C: ... +@overload +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) +def attrs( + maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + auto_detect: bool = ..., + collect_by_mro: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., +) -> Callable[[_C], _C]: ... +@overload +@__dataclass_transform__(field_descriptors=(attrib, field)) +def define( + maybe_cls: _C, + *, + these: Optional[Dict[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., +) -> _C: ... +@overload +@__dataclass_transform__(field_descriptors=(attrib, field)) +def define( + maybe_cls: None = ..., + *, + these: Optional[Dict[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., +) -> Callable[[_C], _C]: ... + +mutable = define +frozen = define # they differ only in their defaults + +def fields(cls: Type[AttrsInstance]) -> Any: ... +def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ... +def validate(inst: AttrsInstance) -> None: ... +def resolve_types( + cls: _C, + globalns: Optional[Dict[str, Any]] = ..., + localns: Optional[Dict[str, Any]] = ..., + attribs: Optional[List[Attribute[Any]]] = ..., +) -> _C: ... + +# TODO: add support for returning a proper attrs class from the mypy plugin +# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', +# [attr.ib()])` is valid +def make_class( + name: str, + attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], + bases: Tuple[type, ...] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[_EqOrderType] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + collect_by_mro: bool = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> type: ... + +# _funcs -- + +# TODO: add support for returning TypedDict from the mypy plugin +# FIXME: asdict/astuple do not honor their factory args. Waiting on one of +# these: +# https://github.com/python/mypy/issues/4236 +# https://github.com/python/typing/issues/253 +# XXX: remember to fix attrs.asdict/astuple too! +def asdict( + inst: AttrsInstance, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + dict_factory: Type[Mapping[Any, Any]] = ..., + retain_collection_types: bool = ..., + value_serializer: Optional[ + Callable[[type, Attribute[Any], Any], Any] + ] = ..., + tuple_keys: Optional[bool] = ..., +) -> Dict[str, Any]: ... + +# TODO: add support for returning NamedTuple from the mypy plugin +def astuple( + inst: AttrsInstance, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + tuple_factory: Type[Sequence[Any]] = ..., + retain_collection_types: bool = ..., +) -> Tuple[Any, ...]: ... +def has(cls: type) -> bool: ... +def assoc(inst: _T, **changes: Any) -> _T: ... +def evolve(inst: _T, **changes: Any) -> _T: ... + +# _config -- + +def set_run_validators(run: bool) -> None: ... +def get_run_validators() -> bool: ... + +# aliases -- + +s = attributes = attrs +ib = attr = attrib +dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) diff --git a/axios-example/lib/python3.10/site-packages/attr/_cmp.py b/axios-example/lib/python3.10/site-packages/attr/_cmp.py new file mode 100644 index 0000000..81b99e4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_cmp.py @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: MIT + + +import functools +import types + +from ._make import _make_ne + + +_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="} + + +def cmp_using( + eq=None, + lt=None, + le=None, + gt=None, + ge=None, + require_same_type=True, + class_name="Comparable", +): + """ + Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and + ``cmp`` arguments to customize field comparison. + + The resulting class will have a full set of ordering methods if + at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. + + :param Optional[callable] eq: `callable` used to evaluate equality + of two objects. + :param Optional[callable] lt: `callable` used to evaluate whether + one object is less than another object. + :param Optional[callable] le: `callable` used to evaluate whether + one object is less than or equal to another object. + :param Optional[callable] gt: `callable` used to evaluate whether + one object is greater than another object. + :param Optional[callable] ge: `callable` used to evaluate whether + one object is greater than or equal to another object. + + :param bool require_same_type: When `True`, equality and ordering methods + will return `NotImplemented` if objects are not of the same type. + + :param Optional[str] class_name: Name of class. Defaults to 'Comparable'. + + See `comparison` for more details. + + .. versionadded:: 21.1.0 + """ + + body = { + "__slots__": ["value"], + "__init__": _make_init(), + "_requirements": [], + "_is_comparable_to": _is_comparable_to, + } + + # Add operations. + num_order_functions = 0 + has_eq_function = False + + if eq is not None: + has_eq_function = True + body["__eq__"] = _make_operator("eq", eq) + body["__ne__"] = _make_ne() + + if lt is not None: + num_order_functions += 1 + body["__lt__"] = _make_operator("lt", lt) + + if le is not None: + num_order_functions += 1 + body["__le__"] = _make_operator("le", le) + + if gt is not None: + num_order_functions += 1 + body["__gt__"] = _make_operator("gt", gt) + + if ge is not None: + num_order_functions += 1 + body["__ge__"] = _make_operator("ge", ge) + + type_ = types.new_class( + class_name, (object,), {}, lambda ns: ns.update(body) + ) + + # Add same type requirement. + if require_same_type: + type_._requirements.append(_check_same_type) + + # Add total ordering if at least one operation was defined. + if 0 < num_order_functions < 4: + if not has_eq_function: + # functools.total_ordering requires __eq__ to be defined, + # so raise early error here to keep a nice stack. + raise ValueError( + "eq must be define is order to complete ordering from " + "lt, le, gt, ge." + ) + type_ = functools.total_ordering(type_) + + return type_ + + +def _make_init(): + """ + Create __init__ method. + """ + + def __init__(self, value): + """ + Initialize object with *value*. + """ + self.value = value + + return __init__ + + +def _make_operator(name, func): + """ + Create operator method. + """ + + def method(self, other): + if not self._is_comparable_to(other): + return NotImplemented + + result = func(self.value, other.value) + if result is NotImplemented: + return NotImplemented + + return result + + method.__name__ = "__%s__" % (name,) + method.__doc__ = "Return a %s b. Computed by attrs." % ( + _operation_names[name], + ) + + return method + + +def _is_comparable_to(self, other): + """ + Check whether `other` is comparable to `self`. + """ + for func in self._requirements: + if not func(self, other): + return False + return True + + +def _check_same_type(self, other): + """ + Return True if *self* and *other* are of the same type, False otherwise. + """ + return other.value.__class__ is self.value.__class__ diff --git a/axios-example/lib/python3.10/site-packages/attr/_cmp.pyi b/axios-example/lib/python3.10/site-packages/attr/_cmp.pyi new file mode 100644 index 0000000..35437ef --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_cmp.pyi @@ -0,0 +1,13 @@ +from typing import Any, Callable, Optional, Type + +_CompareWithType = Callable[[Any, Any], bool] + +def cmp_using( + eq: Optional[_CompareWithType], + lt: Optional[_CompareWithType], + le: Optional[_CompareWithType], + gt: Optional[_CompareWithType], + ge: Optional[_CompareWithType], + require_same_type: bool, + class_name: str, +) -> Type: ... diff --git a/axios-example/lib/python3.10/site-packages/attr/_compat.py b/axios-example/lib/python3.10/site-packages/attr/_compat.py new file mode 100644 index 0000000..5826493 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_compat.py @@ -0,0 +1,185 @@ +# SPDX-License-Identifier: MIT + + +import inspect +import platform +import sys +import threading +import types +import warnings + +from collections.abc import Mapping, Sequence # noqa + + +PYPY = platform.python_implementation() == "PyPy" +PY36 = sys.version_info[:2] >= (3, 6) +HAS_F_STRINGS = PY36 +PY310 = sys.version_info[:2] >= (3, 10) + + +if PYPY or PY36: + ordered_dict = dict +else: + from collections import OrderedDict + + ordered_dict = OrderedDict + + +def just_warn(*args, **kw): + warnings.warn( + "Running interpreter doesn't sufficiently support code object " + "introspection. Some features like bare super() or accessing " + "__class__ will not work with slotted classes.", + RuntimeWarning, + stacklevel=2, + ) + + +class _AnnotationExtractor: + """ + Extract type annotations from a callable, returning None whenever there + is none. + """ + + __slots__ = ["sig"] + + def __init__(self, callable): + try: + self.sig = inspect.signature(callable) + except (ValueError, TypeError): # inspect failed + self.sig = None + + def get_first_param_type(self): + """ + Return the type annotation of the first argument if it's not empty. + """ + if not self.sig: + return None + + params = list(self.sig.parameters.values()) + if params and params[0].annotation is not inspect.Parameter.empty: + return params[0].annotation + + return None + + def get_return_type(self): + """ + Return the return type if it's not empty. + """ + if ( + self.sig + and self.sig.return_annotation is not inspect.Signature.empty + ): + return self.sig.return_annotation + + return None + + +def make_set_closure_cell(): + """Return a function of two arguments (cell, value) which sets + the value stored in the closure cell `cell` to `value`. + """ + # pypy makes this easy. (It also supports the logic below, but + # why not do the easy/fast thing?) + if PYPY: + + def set_closure_cell(cell, value): + cell.__setstate__((value,)) + + return set_closure_cell + + # Otherwise gotta do it the hard way. + + # Create a function that will set its first cellvar to `value`. + def set_first_cellvar_to(value): + x = value + return + + # This function will be eliminated as dead code, but + # not before its reference to `x` forces `x` to be + # represented as a closure cell rather than a local. + def force_x_to_be_a_cell(): # pragma: no cover + return x + + try: + # Extract the code object and make sure our assumptions about + # the closure behavior are correct. + co = set_first_cellvar_to.__code__ + if co.co_cellvars != ("x",) or co.co_freevars != (): + raise AssertionError # pragma: no cover + + # Convert this code object to a code object that sets the + # function's first _freevar_ (not cellvar) to the argument. + if sys.version_info >= (3, 8): + + def set_closure_cell(cell, value): + cell.cell_contents = value + + else: + args = [co.co_argcount] + args.append(co.co_kwonlyargcount) + args.extend( + [ + co.co_nlocals, + co.co_stacksize, + co.co_flags, + co.co_code, + co.co_consts, + co.co_names, + co.co_varnames, + co.co_filename, + co.co_name, + co.co_firstlineno, + co.co_lnotab, + # These two arguments are reversed: + co.co_cellvars, + co.co_freevars, + ] + ) + set_first_freevar_code = types.CodeType(*args) + + def set_closure_cell(cell, value): + # Create a function using the set_first_freevar_code, + # whose first closure cell is `cell`. Calling it will + # change the value of that cell. + setter = types.FunctionType( + set_first_freevar_code, {}, "setter", (), (cell,) + ) + # And call it to set the cell. + setter(value) + + # Make sure it works on this interpreter: + def make_func_with_cell(): + x = None + + def func(): + return x # pragma: no cover + + return func + + cell = make_func_with_cell().__closure__[0] + set_closure_cell(cell, 100) + if cell.cell_contents != 100: + raise AssertionError # pragma: no cover + + except Exception: + return just_warn + else: + return set_closure_cell + + +set_closure_cell = make_set_closure_cell() + +# Thread-local global to track attrs instances which are already being repr'd. +# This is needed because there is no other (thread-safe) way to pass info +# about the instances that are already being repr'd through the call stack +# in order to ensure we don't perform infinite recursion. +# +# For instance, if an instance contains a dict which contains that instance, +# we need to know that we're already repr'ing the outside instance from within +# the dict's repr() call. +# +# This lives here rather than in _make.py so that the functions in _make.py +# don't have a direct reference to the thread-local in their globals dict. +# If they have such a reference, it breaks cloudpickle. +repr_context = threading.local() diff --git a/axios-example/lib/python3.10/site-packages/attr/_config.py b/axios-example/lib/python3.10/site-packages/attr/_config.py new file mode 100644 index 0000000..96d4200 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_config.py @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: MIT + + +__all__ = ["set_run_validators", "get_run_validators"] + +_run_validators = True + + +def set_run_validators(run): + """ + Set whether or not validators are run. By default, they are run. + + .. deprecated:: 21.3.0 It will not be removed, but it also will not be + moved to new ``attrs`` namespace. Use `attrs.validators.set_disabled()` + instead. + """ + if not isinstance(run, bool): + raise TypeError("'run' must be bool.") + global _run_validators + _run_validators = run + + +def get_run_validators(): + """ + Return whether or not validators are run. + + .. deprecated:: 21.3.0 It will not be removed, but it also will not be + moved to new ``attrs`` namespace. Use `attrs.validators.get_disabled()` + instead. + """ + return _run_validators diff --git a/axios-example/lib/python3.10/site-packages/attr/_funcs.py b/axios-example/lib/python3.10/site-packages/attr/_funcs.py new file mode 100644 index 0000000..a982d7c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_funcs.py @@ -0,0 +1,420 @@ +# SPDX-License-Identifier: MIT + + +import copy + +from ._make import NOTHING, _obj_setattr, fields +from .exceptions import AttrsAttributeNotFoundError + + +def asdict( + inst, + recurse=True, + filter=None, + dict_factory=dict, + retain_collection_types=False, + value_serializer=None, +): + """ + Return the ``attrs`` attribute values of *inst* as a dict. + + Optionally recurse into other ``attrs``-decorated classes. + + :param inst: Instance of an ``attrs``-decorated class. + :param bool recurse: Recurse into classes that are also + ``attrs``-decorated. + :param callable filter: A callable whose return code determines whether an + attribute or element is included (``True``) or dropped (``False``). Is + called with the `attrs.Attribute` as the first argument and the + value as the second argument. + :param callable dict_factory: A callable to produce dictionaries from. For + example, to produce ordered dictionaries instead of normal Python + dictionaries, pass in ``collections.OrderedDict``. + :param bool retain_collection_types: Do not convert to ``list`` when + encountering an attribute whose type is ``tuple`` or ``set``. Only + meaningful if ``recurse`` is ``True``. + :param Optional[callable] value_serializer: A hook that is called for every + attribute or dict key/value. It receives the current instance, field + and value and must return the (updated) value. The hook is run *after* + the optional *filter* has been applied. + + :rtype: return type of *dict_factory* + + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 16.0.0 *dict_factory* + .. versionadded:: 16.1.0 *retain_collection_types* + .. versionadded:: 20.3.0 *value_serializer* + .. versionadded:: 21.3.0 If a dict has a collection for a key, it is + serialized as a tuple. + """ + attrs = fields(inst.__class__) + rv = dict_factory() + for a in attrs: + v = getattr(inst, a.name) + if filter is not None and not filter(a, v): + continue + + if value_serializer is not None: + v = value_serializer(inst, a, v) + + if recurse is True: + if has(v.__class__): + rv[a.name] = asdict( + v, + recurse=True, + filter=filter, + dict_factory=dict_factory, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ) + elif isinstance(v, (tuple, list, set, frozenset)): + cf = v.__class__ if retain_collection_types is True else list + rv[a.name] = cf( + [ + _asdict_anything( + i, + is_key=False, + filter=filter, + dict_factory=dict_factory, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ) + for i in v + ] + ) + elif isinstance(v, dict): + df = dict_factory + rv[a.name] = df( + ( + _asdict_anything( + kk, + is_key=True, + filter=filter, + dict_factory=df, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ), + _asdict_anything( + vv, + is_key=False, + filter=filter, + dict_factory=df, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ), + ) + for kk, vv in v.items() + ) + else: + rv[a.name] = v + else: + rv[a.name] = v + return rv + + +def _asdict_anything( + val, + is_key, + filter, + dict_factory, + retain_collection_types, + value_serializer, +): + """ + ``asdict`` only works on attrs instances, this works on anything. + """ + if getattr(val.__class__, "__attrs_attrs__", None) is not None: + # Attrs class. + rv = asdict( + val, + recurse=True, + filter=filter, + dict_factory=dict_factory, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ) + elif isinstance(val, (tuple, list, set, frozenset)): + if retain_collection_types is True: + cf = val.__class__ + elif is_key: + cf = tuple + else: + cf = list + + rv = cf( + [ + _asdict_anything( + i, + is_key=False, + filter=filter, + dict_factory=dict_factory, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ) + for i in val + ] + ) + elif isinstance(val, dict): + df = dict_factory + rv = df( + ( + _asdict_anything( + kk, + is_key=True, + filter=filter, + dict_factory=df, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ), + _asdict_anything( + vv, + is_key=False, + filter=filter, + dict_factory=df, + retain_collection_types=retain_collection_types, + value_serializer=value_serializer, + ), + ) + for kk, vv in val.items() + ) + else: + rv = val + if value_serializer is not None: + rv = value_serializer(None, None, rv) + + return rv + + +def astuple( + inst, + recurse=True, + filter=None, + tuple_factory=tuple, + retain_collection_types=False, +): + """ + Return the ``attrs`` attribute values of *inst* as a tuple. + + Optionally recurse into other ``attrs``-decorated classes. + + :param inst: Instance of an ``attrs``-decorated class. + :param bool recurse: Recurse into classes that are also + ``attrs``-decorated. + :param callable filter: A callable whose return code determines whether an + attribute or element is included (``True``) or dropped (``False``). Is + called with the `attrs.Attribute` as the first argument and the + value as the second argument. + :param callable tuple_factory: A callable to produce tuples from. For + example, to produce lists instead of tuples. + :param bool retain_collection_types: Do not convert to ``list`` + or ``dict`` when encountering an attribute which type is + ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is + ``True``. + + :rtype: return type of *tuple_factory* + + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 16.2.0 + """ + attrs = fields(inst.__class__) + rv = [] + retain = retain_collection_types # Very long. :/ + for a in attrs: + v = getattr(inst, a.name) + if filter is not None and not filter(a, v): + continue + if recurse is True: + if has(v.__class__): + rv.append( + astuple( + v, + recurse=True, + filter=filter, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + ) + elif isinstance(v, (tuple, list, set, frozenset)): + cf = v.__class__ if retain is True else list + rv.append( + cf( + [ + astuple( + j, + recurse=True, + filter=filter, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(j.__class__) + else j + for j in v + ] + ) + ) + elif isinstance(v, dict): + df = v.__class__ if retain is True else dict + rv.append( + df( + ( + astuple( + kk, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(kk.__class__) + else kk, + astuple( + vv, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(vv.__class__) + else vv, + ) + for kk, vv in v.items() + ) + ) + else: + rv.append(v) + else: + rv.append(v) + + return rv if tuple_factory is list else tuple_factory(rv) + + +def has(cls): + """ + Check whether *cls* is a class with ``attrs`` attributes. + + :param type cls: Class to introspect. + :raise TypeError: If *cls* is not a class. + + :rtype: bool + """ + return getattr(cls, "__attrs_attrs__", None) is not None + + +def assoc(inst, **changes): + """ + Copy *inst* and apply *changes*. + + :param inst: Instance of a class with ``attrs`` attributes. + :param changes: Keyword changes in the new copy. + + :return: A copy of inst with *changes* incorporated. + + :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't + be found on *cls*. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. deprecated:: 17.1.0 + Use `attrs.evolve` instead if you can. + This function will not be removed du to the slightly different approach + compared to `attrs.evolve`. + """ + import warnings + + warnings.warn( + "assoc is deprecated and will be removed after 2018/01.", + DeprecationWarning, + stacklevel=2, + ) + new = copy.copy(inst) + attrs = fields(inst.__class__) + for k, v in changes.items(): + a = getattr(attrs, k, NOTHING) + if a is NOTHING: + raise AttrsAttributeNotFoundError( + "{k} is not an attrs attribute on {cl}.".format( + k=k, cl=new.__class__ + ) + ) + _obj_setattr(new, k, v) + return new + + +def evolve(inst, **changes): + """ + Create a new instance, based on *inst* with *changes* applied. + + :param inst: Instance of a class with ``attrs`` attributes. + :param changes: Keyword changes in the new copy. + + :return: A copy of inst with *changes* incorporated. + + :raise TypeError: If *attr_name* couldn't be found in the class + ``__init__``. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 17.1.0 + """ + cls = inst.__class__ + attrs = fields(cls) + for a in attrs: + if not a.init: + continue + attr_name = a.name # To deal with private attributes. + init_name = attr_name if attr_name[0] != "_" else attr_name[1:] + if init_name not in changes: + changes[init_name] = getattr(inst, attr_name) + + return cls(**changes) + + +def resolve_types(cls, globalns=None, localns=None, attribs=None): + """ + Resolve any strings and forward annotations in type annotations. + + This is only required if you need concrete types in `Attribute`'s *type* + field. In other words, you don't need to resolve your types if you only + use them for static type checking. + + With no arguments, names will be looked up in the module in which the class + was created. If this is not what you want, e.g. if the name only exists + inside a method, you may pass *globalns* or *localns* to specify other + dictionaries in which to look up these names. See the docs of + `typing.get_type_hints` for more details. + + :param type cls: Class to resolve. + :param Optional[dict] globalns: Dictionary containing global variables. + :param Optional[dict] localns: Dictionary containing local variables. + :param Optional[list] attribs: List of attribs for the given class. + This is necessary when calling from inside a ``field_transformer`` + since *cls* is not an ``attrs`` class yet. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class and you didn't pass any attribs. + :raise NameError: If types cannot be resolved because of missing variables. + + :returns: *cls* so you can use this function also as a class decorator. + Please note that you have to apply it **after** `attrs.define`. That + means the decorator has to come in the line **before** `attrs.define`. + + .. versionadded:: 20.1.0 + .. versionadded:: 21.1.0 *attribs* + + """ + # Since calling get_type_hints is expensive we cache whether we've + # done it already. + if getattr(cls, "__attrs_types_resolved__", None) != cls: + import typing + + hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) + for field in fields(cls) if attribs is None else attribs: + if field.name in hints: + # Since fields have been frozen we must work around it. + _obj_setattr(field, "type", hints[field.name]) + # We store the class we resolved so that subclasses know they haven't + # been resolved. + cls.__attrs_types_resolved__ = cls + + # Return the class so you can use it as a decorator too. + return cls diff --git a/axios-example/lib/python3.10/site-packages/attr/_make.py b/axios-example/lib/python3.10/site-packages/attr/_make.py new file mode 100644 index 0000000..4d1afe3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_make.py @@ -0,0 +1,3006 @@ +# SPDX-License-Identifier: MIT + +import copy +import linecache +import sys +import types +import typing + +from operator import itemgetter + +# We need to import _compat itself in addition to the _compat members to avoid +# having the thread-local in the globals here. +from . import _compat, _config, setters +from ._compat import ( + HAS_F_STRINGS, + PY310, + PYPY, + _AnnotationExtractor, + ordered_dict, + set_closure_cell, +) +from .exceptions import ( + DefaultAlreadySetError, + FrozenInstanceError, + NotAnAttrsClassError, + UnannotatedAttributeError, +) + + +# This is used at least twice, so cache it here. +_obj_setattr = object.__setattr__ +_init_converter_pat = "__attr_converter_%s" +_init_factory_pat = "__attr_factory_{}" +_tuple_property_pat = ( + " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" +) +_classvar_prefixes = ( + "typing.ClassVar", + "t.ClassVar", + "ClassVar", + "typing_extensions.ClassVar", +) +# we don't use a double-underscore prefix because that triggers +# name mangling when trying to create a slot for the field +# (when slots=True) +_hash_cache_field = "_attrs_cached_hash" + +_empty_metadata_singleton = types.MappingProxyType({}) + +# Unique object for unequivocal getattr() defaults. +_sentinel = object() + +_ng_default_on_setattr = setters.pipe(setters.convert, setters.validate) + + +class _Nothing: + """ + Sentinel class to indicate the lack of a value when ``None`` is ambiguous. + + ``_Nothing`` is a singleton. There is only ever one of it. + + .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. + """ + + _singleton = None + + def __new__(cls): + if _Nothing._singleton is None: + _Nothing._singleton = super().__new__(cls) + return _Nothing._singleton + + def __repr__(self): + return "NOTHING" + + def __bool__(self): + return False + + +NOTHING = _Nothing() +""" +Sentinel to indicate the lack of a value when ``None`` is ambiguous. +""" + + +class _CacheHashWrapper(int): + """ + An integer subclass that pickles / copies as None + + This is used for non-slots classes with ``cache_hash=True``, to avoid + serializing a potentially (even likely) invalid hash value. Since ``None`` + is the default value for uncalculated hashes, whenever this is copied, + the copy's value for the hash should automatically reset. + + See GH #613 for more details. + """ + + def __reduce__(self, _none_constructor=type(None), _args=()): + return _none_constructor, _args + + +def attrib( + default=NOTHING, + validator=None, + repr=True, + cmp=None, + hash=None, + init=True, + metadata=None, + type=None, + converter=None, + factory=None, + kw_only=False, + eq=None, + order=None, + on_setattr=None, +): + """ + Create a new attribute on a class. + + .. warning:: + + Does *not* do anything unless the class is also decorated with + `attr.s`! + + :param default: A value that is used if an ``attrs``-generated ``__init__`` + is used and no value is passed while instantiating or the attribute is + excluded using ``init=False``. + + If the value is an instance of `attrs.Factory`, its callable will be + used to construct a new value (useful for mutable data types like lists + or dicts). + + If a default is not set (or set manually to `attrs.NOTHING`), a value + *must* be supplied when instantiating; otherwise a `TypeError` + will be raised. + + The default can also be set using decorator notation as shown below. + + :type default: Any value + + :param callable factory: Syntactic sugar for + ``default=attr.Factory(factory)``. + + :param validator: `callable` that is called by ``attrs``-generated + ``__init__`` methods after the instance has been initialized. They + receive the initialized instance, the :func:`~attrs.Attribute`, and the + passed value. + + The return value is *not* inspected so the validator has to throw an + exception itself. + + If a `list` is passed, its items are treated as validators and must + all pass. + + Validators can be globally disabled and re-enabled using + `get_run_validators`. + + The validator can also be set using decorator notation as shown below. + + :type validator: `callable` or a `list` of `callable`\\ s. + + :param repr: Include this attribute in the generated ``__repr__`` + method. If ``True``, include the attribute; if ``False``, omit it. By + default, the built-in ``repr()`` function is used. To override how the + attribute value is formatted, pass a ``callable`` that takes a single + value and returns a string. Note that the resulting string is used + as-is, i.e. it will be used directly *instead* of calling ``repr()`` + (the default). + :type repr: a `bool` or a `callable` to use a custom function. + + :param eq: If ``True`` (default), include this attribute in the + generated ``__eq__`` and ``__ne__`` methods that check two instances + for equality. To override how the attribute value is compared, + pass a ``callable`` that takes a single value and returns the value + to be compared. + :type eq: a `bool` or a `callable`. + + :param order: If ``True`` (default), include this attributes in the + generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. + To override how the attribute value is ordered, + pass a ``callable`` that takes a single value and returns the value + to be ordered. + :type order: a `bool` or a `callable`. + + :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the + same value. Must not be mixed with *eq* or *order*. + :type cmp: a `bool` or a `callable`. + + :param Optional[bool] hash: Include this attribute in the generated + ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This + is the correct behavior according the Python spec. Setting this value + to anything else than ``None`` is *discouraged*. + :param bool init: Include this attribute in the generated ``__init__`` + method. It is possible to set this to ``False`` and set a default + value. In that case this attributed is unconditionally initialized + with the specified default value or factory. + :param callable converter: `callable` that is called by + ``attrs``-generated ``__init__`` methods to convert attribute's value + to the desired format. It is given the passed-in value, and the + returned value will be used as the new value of the attribute. The + value is converted before being passed to the validator, if any. + :param metadata: An arbitrary mapping, to be used by third-party + components. See `extending_metadata`. + :param type: The type of the attribute. In Python 3.6 or greater, the + preferred method to specify the type is using a variable annotation + (see :pep:`526`). + This argument is provided for backward compatibility. + Regardless of the approach used, the type will be stored on + ``Attribute.type``. + + Please note that ``attrs`` doesn't do anything with this metadata by + itself. You can use it as part of your own code or for + `static type checking `. + :param kw_only: Make this attribute keyword-only (Python 3+) + in the generated ``__init__`` (if ``init`` is ``False``, this + parameter is ignored). + :param on_setattr: Allows to overwrite the *on_setattr* setting from + `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used. + Set to `attrs.setters.NO_OP` to run **no** `setattr` hooks for this + attribute -- regardless of the setting in `attr.s`. + :type on_setattr: `callable`, or a list of callables, or `None`, or + `attrs.setters.NO_OP` + + .. versionadded:: 15.2.0 *convert* + .. versionadded:: 16.3.0 *metadata* + .. versionchanged:: 17.1.0 *validator* can be a ``list`` now. + .. versionchanged:: 17.1.0 + *hash* is ``None`` and therefore mirrors *eq* by default. + .. versionadded:: 17.3.0 *type* + .. deprecated:: 17.4.0 *convert* + .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated + *convert* to achieve consistency with other noun-based arguments. + .. versionadded:: 18.1.0 + ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. + .. versionadded:: 18.2.0 *kw_only* + .. versionchanged:: 19.2.0 *convert* keyword argument removed. + .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. + .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. + .. versionadded:: 19.2.0 *eq* and *order* + .. versionadded:: 20.1.0 *on_setattr* + .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 + .. versionchanged:: 21.1.0 + *eq*, *order*, and *cmp* also accept a custom callable + .. versionchanged:: 21.1.0 *cmp* undeprecated + """ + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq, order, True + ) + + if hash is not None and hash is not True and hash is not False: + raise TypeError( + "Invalid value for hash. Must be True, False, or None." + ) + + if factory is not None: + if default is not NOTHING: + raise ValueError( + "The `default` and `factory` arguments are mutually " + "exclusive." + ) + if not callable(factory): + raise ValueError("The `factory` argument must be a callable.") + default = Factory(factory) + + if metadata is None: + metadata = {} + + # Apply syntactic sugar by auto-wrapping. + if isinstance(on_setattr, (list, tuple)): + on_setattr = setters.pipe(*on_setattr) + + if validator and isinstance(validator, (list, tuple)): + validator = and_(*validator) + + if converter and isinstance(converter, (list, tuple)): + converter = pipe(*converter) + + return _CountingAttr( + default=default, + validator=validator, + repr=repr, + cmp=None, + hash=hash, + init=init, + converter=converter, + metadata=metadata, + type=type, + kw_only=kw_only, + eq=eq, + eq_key=eq_key, + order=order, + order_key=order_key, + on_setattr=on_setattr, + ) + + +def _compile_and_eval(script, globs, locs=None, filename=""): + """ + "Exec" the script with the given global (globs) and local (locs) variables. + """ + bytecode = compile(script, filename, "exec") + eval(bytecode, globs, locs) + + +def _make_method(name, script, filename, globs): + """ + Create the method with the script given and return the method object. + """ + locs = {} + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + count = 1 + base_filename = filename + while True: + linecache_tuple = ( + len(script), + None, + script.splitlines(True), + filename, + ) + old_val = linecache.cache.setdefault(filename, linecache_tuple) + if old_val == linecache_tuple: + break + else: + filename = "{}-{}>".format(base_filename[:-1], count) + count += 1 + + _compile_and_eval(script, globs, locs, filename) + + return locs[name] + + +def _make_attr_tuple_class(cls_name, attr_names): + """ + Create a tuple subclass to hold `Attribute`s for an `attrs` class. + + The subclass is a bare tuple with properties for names. + + class MyClassAttributes(tuple): + __slots__ = () + x = property(itemgetter(0)) + """ + attr_class_name = "{}Attributes".format(cls_name) + attr_class_template = [ + "class {}(tuple):".format(attr_class_name), + " __slots__ = ()", + ] + if attr_names: + for i, attr_name in enumerate(attr_names): + attr_class_template.append( + _tuple_property_pat.format(index=i, attr_name=attr_name) + ) + else: + attr_class_template.append(" pass") + globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} + _compile_and_eval("\n".join(attr_class_template), globs) + return globs[attr_class_name] + + +# Tuple class for extracted attributes from a class definition. +# `base_attrs` is a subset of `attrs`. +_Attributes = _make_attr_tuple_class( + "_Attributes", + [ + # all attributes to build dunder methods for + "attrs", + # attributes that have been inherited + "base_attrs", + # map inherited attributes to their originating classes + "base_attrs_map", + ], +) + + +def _is_class_var(annot): + """ + Check whether *annot* is a typing.ClassVar. + + The string comparison hack is used to avoid evaluating all string + annotations which would put attrs-based classes at a performance + disadvantage compared to plain old classes. + """ + annot = str(annot) + + # Annotation can be quoted. + if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): + annot = annot[1:-1] + + return annot.startswith(_classvar_prefixes) + + +def _has_own_attribute(cls, attrib_name): + """ + Check whether *cls* defines *attrib_name* (and doesn't just inherit it). + + Requires Python 3. + """ + attr = getattr(cls, attrib_name, _sentinel) + if attr is _sentinel: + return False + + for base_cls in cls.__mro__[1:]: + a = getattr(base_cls, attrib_name, None) + if attr is a: + return False + + return True + + +def _get_annotations(cls): + """ + Get annotations for *cls*. + """ + if _has_own_attribute(cls, "__annotations__"): + return cls.__annotations__ + + return {} + + +def _counter_getter(e): + """ + Key function for sorting to avoid re-creating a lambda for every class. + """ + return e[1].counter + + +def _collect_base_attrs(cls, taken_attr_names): + """ + Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. + """ + base_attrs = [] + base_attr_map = {} # A dictionary of base attrs to their classes. + + # Traverse the MRO and collect attributes. + for base_cls in reversed(cls.__mro__[1:-1]): + for a in getattr(base_cls, "__attrs_attrs__", []): + if a.inherited or a.name in taken_attr_names: + continue + + a = a.evolve(inherited=True) + base_attrs.append(a) + base_attr_map[a.name] = base_cls + + # For each name, only keep the freshest definition i.e. the furthest at the + # back. base_attr_map is fine because it gets overwritten with every new + # instance. + filtered = [] + seen = set() + for a in reversed(base_attrs): + if a.name in seen: + continue + filtered.insert(0, a) + seen.add(a.name) + + return filtered, base_attr_map + + +def _collect_base_attrs_broken(cls, taken_attr_names): + """ + Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. + + N.B. *taken_attr_names* will be mutated. + + Adhere to the old incorrect behavior. + + Notably it collects from the front and considers inherited attributes which + leads to the buggy behavior reported in #428. + """ + base_attrs = [] + base_attr_map = {} # A dictionary of base attrs to their classes. + + # Traverse the MRO and collect attributes. + for base_cls in cls.__mro__[1:-1]: + for a in getattr(base_cls, "__attrs_attrs__", []): + if a.name in taken_attr_names: + continue + + a = a.evolve(inherited=True) + taken_attr_names.add(a.name) + base_attrs.append(a) + base_attr_map[a.name] = base_cls + + return base_attrs, base_attr_map + + +def _transform_attrs( + cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer +): + """ + Transform all `_CountingAttr`s on a class into `Attribute`s. + + If *these* is passed, use that and don't look for them on the class. + + *collect_by_mro* is True, collect them in the correct MRO order, otherwise + use the old -- incorrect -- order. See #428. + + Return an `_Attributes`. + """ + cd = cls.__dict__ + anns = _get_annotations(cls) + + if these is not None: + ca_list = [(name, ca) for name, ca in these.items()] + + if not isinstance(these, ordered_dict): + ca_list.sort(key=_counter_getter) + elif auto_attribs is True: + ca_names = { + name + for name, attr in cd.items() + if isinstance(attr, _CountingAttr) + } + ca_list = [] + annot_names = set() + for attr_name, type in anns.items(): + if _is_class_var(type): + continue + annot_names.add(attr_name) + a = cd.get(attr_name, NOTHING) + + if not isinstance(a, _CountingAttr): + if a is NOTHING: + a = attrib() + else: + a = attrib(default=a) + ca_list.append((attr_name, a)) + + unannotated = ca_names - annot_names + if len(unannotated) > 0: + raise UnannotatedAttributeError( + "The following `attr.ib`s lack a type annotation: " + + ", ".join( + sorted(unannotated, key=lambda n: cd.get(n).counter) + ) + + "." + ) + else: + ca_list = sorted( + ( + (name, attr) + for name, attr in cd.items() + if isinstance(attr, _CountingAttr) + ), + key=lambda e: e[1].counter, + ) + + own_attrs = [ + Attribute.from_counting_attr( + name=attr_name, ca=ca, type=anns.get(attr_name) + ) + for attr_name, ca in ca_list + ] + + if collect_by_mro: + base_attrs, base_attr_map = _collect_base_attrs( + cls, {a.name for a in own_attrs} + ) + else: + base_attrs, base_attr_map = _collect_base_attrs_broken( + cls, {a.name for a in own_attrs} + ) + + if kw_only: + own_attrs = [a.evolve(kw_only=True) for a in own_attrs] + base_attrs = [a.evolve(kw_only=True) for a in base_attrs] + + attrs = base_attrs + own_attrs + + # Mandatory vs non-mandatory attr order only matters when they are part of + # the __init__ signature and when they aren't kw_only (which are moved to + # the end and can be mandatory or non-mandatory in any order, as they will + # be specified as keyword args anyway). Check the order of those attrs: + had_default = False + for a in (a for a in attrs if a.init is not False and a.kw_only is False): + if had_default is True and a.default is NOTHING: + raise ValueError( + "No mandatory attributes allowed after an attribute with a " + "default value or factory. Attribute in question: %r" % (a,) + ) + + if had_default is False and a.default is not NOTHING: + had_default = True + + if field_transformer is not None: + attrs = field_transformer(cls, attrs) + + # Create AttrsClass *after* applying the field_transformer since it may + # add or remove attributes! + attr_names = [a.name for a in attrs] + AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) + + return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map)) + + +if PYPY: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + if isinstance(self, BaseException) and name in ( + "__cause__", + "__context__", + ): + BaseException.__setattr__(self, name, value) + return + + raise FrozenInstanceError() + +else: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + raise FrozenInstanceError() + + +def _frozen_delattrs(self, name): + """ + Attached to frozen classes as __delattr__. + """ + raise FrozenInstanceError() + + +class _ClassBuilder: + """ + Iteratively build *one* class. + """ + + __slots__ = ( + "_attr_names", + "_attrs", + "_base_attr_map", + "_base_names", + "_cache_hash", + "_cls", + "_cls_dict", + "_delete_attribs", + "_frozen", + "_has_pre_init", + "_has_post_init", + "_is_exc", + "_on_setattr", + "_slots", + "_weakref_slot", + "_wrote_own_setattr", + "_has_custom_setattr", + ) + + def __init__( + self, + cls, + these, + slots, + frozen, + weakref_slot, + getstate_setstate, + auto_attribs, + kw_only, + cache_hash, + is_exc, + collect_by_mro, + on_setattr, + has_custom_setattr, + field_transformer, + ): + attrs, base_attrs, base_map = _transform_attrs( + cls, + these, + auto_attribs, + kw_only, + collect_by_mro, + field_transformer, + ) + + self._cls = cls + self._cls_dict = dict(cls.__dict__) if slots else {} + self._attrs = attrs + self._base_names = {a.name for a in base_attrs} + self._base_attr_map = base_map + self._attr_names = tuple(a.name for a in attrs) + self._slots = slots + self._frozen = frozen + self._weakref_slot = weakref_slot + self._cache_hash = cache_hash + self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) + self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) + self._delete_attribs = not bool(these) + self._is_exc = is_exc + self._on_setattr = on_setattr + + self._has_custom_setattr = has_custom_setattr + self._wrote_own_setattr = False + + self._cls_dict["__attrs_attrs__"] = self._attrs + + if frozen: + self._cls_dict["__setattr__"] = _frozen_setattrs + self._cls_dict["__delattr__"] = _frozen_delattrs + + self._wrote_own_setattr = True + elif on_setattr in ( + _ng_default_on_setattr, + setters.validate, + setters.convert, + ): + has_validator = has_converter = False + for a in attrs: + if a.validator is not None: + has_validator = True + if a.converter is not None: + has_converter = True + + if has_validator and has_converter: + break + if ( + ( + on_setattr == _ng_default_on_setattr + and not (has_validator or has_converter) + ) + or (on_setattr == setters.validate and not has_validator) + or (on_setattr == setters.convert and not has_converter) + ): + # If class-level on_setattr is set to convert + validate, but + # there's no field to convert or validate, pretend like there's + # no on_setattr. + self._on_setattr = None + + if getstate_setstate: + ( + self._cls_dict["__getstate__"], + self._cls_dict["__setstate__"], + ) = self._make_getstate_setstate() + + def __repr__(self): + return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__) + + def build_class(self): + """ + Finalize class based on the accumulated configuration. + + Builder cannot be used after calling this method. + """ + if self._slots is True: + return self._create_slots_class() + else: + return self._patch_original_class() + + def _patch_original_class(self): + """ + Apply accumulated methods and return the class. + """ + cls = self._cls + base_names = self._base_names + + # Clean class of attribute definitions (`attr.ib()`s). + if self._delete_attribs: + for name in self._attr_names: + if ( + name not in base_names + and getattr(cls, name, _sentinel) is not _sentinel + ): + try: + delattr(cls, name) + except AttributeError: + # This can happen if a base class defines a class + # variable and we want to set an attribute with the + # same name by using only a type annotation. + pass + + # Attach our dunder methods. + for name, value in self._cls_dict.items(): + setattr(cls, name, value) + + # If we've inherited an attrs __setattr__ and don't write our own, + # reset it to object's. + if not self._wrote_own_setattr and getattr( + cls, "__attrs_own_setattr__", False + ): + cls.__attrs_own_setattr__ = False + + if not self._has_custom_setattr: + cls.__setattr__ = _obj_setattr + + return cls + + def _create_slots_class(self): + """ + Build and return a new class with a `__slots__` attribute. + """ + cd = { + k: v + for k, v in self._cls_dict.items() + if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") + } + + # If our class doesn't have its own implementation of __setattr__ + # (either from the user or by us), check the bases, if one of them has + # an attrs-made __setattr__, that needs to be reset. We don't walk the + # MRO because we only care about our immediate base classes. + # XXX: This can be confused by subclassing a slotted attrs class with + # XXX: a non-attrs class and subclass the resulting class with an attrs + # XXX: class. See `test_slotted_confused` for details. For now that's + # XXX: OK with us. + if not self._wrote_own_setattr: + cd["__attrs_own_setattr__"] = False + + if not self._has_custom_setattr: + for base_cls in self._cls.__bases__: + if base_cls.__dict__.get("__attrs_own_setattr__", False): + cd["__setattr__"] = _obj_setattr + break + + # Traverse the MRO to collect existing slots + # and check for an existing __weakref__. + existing_slots = dict() + weakref_inherited = False + for base_cls in self._cls.__mro__[1:-1]: + if base_cls.__dict__.get("__weakref__", None) is not None: + weakref_inherited = True + existing_slots.update( + { + name: getattr(base_cls, name) + for name in getattr(base_cls, "__slots__", []) + } + ) + + base_names = set(self._base_names) + + names = self._attr_names + if ( + self._weakref_slot + and "__weakref__" not in getattr(self._cls, "__slots__", ()) + and "__weakref__" not in names + and not weakref_inherited + ): + names += ("__weakref__",) + + # We only add the names of attributes that aren't inherited. + # Setting __slots__ to inherited attributes wastes memory. + slot_names = [name for name in names if name not in base_names] + # There are slots for attributes from current class + # that are defined in parent classes. + # As their descriptors may be overridden by a child class, + # we collect them here and update the class dict + reused_slots = { + slot: slot_descriptor + for slot, slot_descriptor in existing_slots.items() + if slot in slot_names + } + slot_names = [name for name in slot_names if name not in reused_slots] + cd.update(reused_slots) + if self._cache_hash: + slot_names.append(_hash_cache_field) + cd["__slots__"] = tuple(slot_names) + + cd["__qualname__"] = self._cls.__qualname__ + + # Create new class based on old class and our methods. + cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd) + + # The following is a fix for + # . On Python 3, + # if a method mentions `__class__` or uses the no-arg super(), the + # compiler will bake a reference to the class in the method itself + # as `method.__closure__`. Since we replace the class with a + # clone, we rewrite these references so it keeps working. + for item in cls.__dict__.values(): + if isinstance(item, (classmethod, staticmethod)): + # Class- and staticmethods hide their functions inside. + # These might need to be rewritten as well. + closure_cells = getattr(item.__func__, "__closure__", None) + elif isinstance(item, property): + # Workaround for property `super()` shortcut (PY3-only). + # There is no universal way for other descriptors. + closure_cells = getattr(item.fget, "__closure__", None) + else: + closure_cells = getattr(item, "__closure__", None) + + if not closure_cells: # Catch None or the empty list. + continue + for cell in closure_cells: + try: + match = cell.cell_contents is self._cls + except ValueError: # ValueError: Cell is empty + pass + else: + if match: + set_closure_cell(cell, cls) + + return cls + + def add_repr(self, ns): + self._cls_dict["__repr__"] = self._add_method_dunders( + _make_repr(self._attrs, ns, self._cls) + ) + return self + + def add_str(self): + repr = self._cls_dict.get("__repr__") + if repr is None: + raise ValueError( + "__str__ can only be generated if a __repr__ exists." + ) + + def __str__(self): + return self.__repr__() + + self._cls_dict["__str__"] = self._add_method_dunders(__str__) + return self + + def _make_getstate_setstate(self): + """ + Create custom __setstate__ and __getstate__ methods. + """ + # __weakref__ is not writable. + state_attr_names = tuple( + an for an in self._attr_names if an != "__weakref__" + ) + + def slots_getstate(self): + """ + Automatically created by attrs. + """ + return tuple(getattr(self, name) for name in state_attr_names) + + hash_caching_enabled = self._cache_hash + + def slots_setstate(self, state): + """ + Automatically created by attrs. + """ + __bound_setattr = _obj_setattr.__get__(self, Attribute) + for name, value in zip(state_attr_names, state): + __bound_setattr(name, value) + + # The hash code cache is not included when the object is + # serialized, but it still needs to be initialized to None to + # indicate that the first call to __hash__ should be a cache + # miss. + if hash_caching_enabled: + __bound_setattr(_hash_cache_field, None) + + return slots_getstate, slots_setstate + + def make_unhashable(self): + self._cls_dict["__hash__"] = None + return self + + def add_hash(self): + self._cls_dict["__hash__"] = self._add_method_dunders( + _make_hash( + self._cls, + self._attrs, + frozen=self._frozen, + cache_hash=self._cache_hash, + ) + ) + + return self + + def add_init(self): + self._cls_dict["__init__"] = self._add_method_dunders( + _make_init( + self._cls, + self._attrs, + self._has_pre_init, + self._has_post_init, + self._frozen, + self._slots, + self._cache_hash, + self._base_attr_map, + self._is_exc, + self._on_setattr, + attrs_init=False, + ) + ) + + return self + + def add_match_args(self): + self._cls_dict["__match_args__"] = tuple( + field.name + for field in self._attrs + if field.init and not field.kw_only + ) + + def add_attrs_init(self): + self._cls_dict["__attrs_init__"] = self._add_method_dunders( + _make_init( + self._cls, + self._attrs, + self._has_pre_init, + self._has_post_init, + self._frozen, + self._slots, + self._cache_hash, + self._base_attr_map, + self._is_exc, + self._on_setattr, + attrs_init=True, + ) + ) + + return self + + def add_eq(self): + cd = self._cls_dict + + cd["__eq__"] = self._add_method_dunders( + _make_eq(self._cls, self._attrs) + ) + cd["__ne__"] = self._add_method_dunders(_make_ne()) + + return self + + def add_order(self): + cd = self._cls_dict + + cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = ( + self._add_method_dunders(meth) + for meth in _make_order(self._cls, self._attrs) + ) + + return self + + def add_setattr(self): + if self._frozen: + return self + + sa_attrs = {} + for a in self._attrs: + on_setattr = a.on_setattr or self._on_setattr + if on_setattr and on_setattr is not setters.NO_OP: + sa_attrs[a.name] = a, on_setattr + + if not sa_attrs: + return self + + if self._has_custom_setattr: + # We need to write a __setattr__ but there already is one! + raise ValueError( + "Can't combine custom __setattr__ with on_setattr hooks." + ) + + # docstring comes from _add_method_dunders + def __setattr__(self, name, val): + try: + a, hook = sa_attrs[name] + except KeyError: + nval = val + else: + nval = hook(self, a, val) + + _obj_setattr(self, name, nval) + + self._cls_dict["__attrs_own_setattr__"] = True + self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__) + self._wrote_own_setattr = True + + return self + + def _add_method_dunders(self, method): + """ + Add __module__ and __qualname__ to a *method* if possible. + """ + try: + method.__module__ = self._cls.__module__ + except AttributeError: + pass + + try: + method.__qualname__ = ".".join( + (self._cls.__qualname__, method.__name__) + ) + except AttributeError: + pass + + try: + method.__doc__ = "Method generated by attrs for class %s." % ( + self._cls.__qualname__, + ) + except AttributeError: + pass + + return method + + +def _determine_attrs_eq_order(cmp, eq, order, default_eq): + """ + Validate the combination of *cmp*, *eq*, and *order*. Derive the effective + values of eq and order. If *eq* is None, set it to *default_eq*. + """ + if cmp is not None and any((eq is not None, order is not None)): + raise ValueError("Don't mix `cmp` with `eq' and `order`.") + + # cmp takes precedence due to bw-compatibility. + if cmp is not None: + return cmp, cmp + + # If left None, equality is set to the specified default and ordering + # mirrors equality. + if eq is None: + eq = default_eq + + if order is None: + order = eq + + if eq is False and order is True: + raise ValueError("`order` can only be True if `eq` is True too.") + + return eq, order + + +def _determine_attrib_eq_order(cmp, eq, order, default_eq): + """ + Validate the combination of *cmp*, *eq*, and *order*. Derive the effective + values of eq and order. If *eq* is None, set it to *default_eq*. + """ + if cmp is not None and any((eq is not None, order is not None)): + raise ValueError("Don't mix `cmp` with `eq' and `order`.") + + def decide_callable_or_boolean(value): + """ + Decide whether a key function is used. + """ + if callable(value): + value, key = True, value + else: + key = None + return value, key + + # cmp takes precedence due to bw-compatibility. + if cmp is not None: + cmp, cmp_key = decide_callable_or_boolean(cmp) + return cmp, cmp_key, cmp, cmp_key + + # If left None, equality is set to the specified default and ordering + # mirrors equality. + if eq is None: + eq, eq_key = default_eq, None + else: + eq, eq_key = decide_callable_or_boolean(eq) + + if order is None: + order, order_key = eq, eq_key + else: + order, order_key = decide_callable_or_boolean(order) + + if eq is False and order is True: + raise ValueError("`order` can only be True if `eq` is True too.") + + return eq, eq_key, order, order_key + + +def _determine_whether_to_implement( + cls, flag, auto_detect, dunders, default=True +): + """ + Check whether we should implement a set of methods for *cls*. + + *flag* is the argument passed into @attr.s like 'init', *auto_detect* the + same as passed into @attr.s and *dunders* is a tuple of attribute names + whose presence signal that the user has implemented it themselves. + + Return *default* if no reason for either for or against is found. + """ + if flag is True or flag is False: + return flag + + if flag is None and auto_detect is False: + return default + + # Logically, flag is None and auto_detect is True here. + for dunder in dunders: + if _has_own_attribute(cls, dunder): + return False + + return default + + +def attrs( + maybe_cls=None, + these=None, + repr_ns=None, + repr=None, + cmp=None, + hash=None, + init=None, + slots=False, + frozen=False, + weakref_slot=True, + str=False, + auto_attribs=False, + kw_only=False, + cache_hash=False, + auto_exc=False, + eq=None, + order=None, + auto_detect=False, + collect_by_mro=False, + getstate_setstate=None, + on_setattr=None, + field_transformer=None, + match_args=True, +): + r""" + A class decorator that adds `dunder + `_\ -methods according to the + specified attributes using `attr.ib` or the *these* argument. + + :param these: A dictionary of name to `attr.ib` mappings. This is + useful to avoid the definition of your attributes within the class body + because you can't (e.g. if you want to add ``__repr__`` methods to + Django models) or don't want to. + + If *these* is not ``None``, ``attrs`` will *not* search the class body + for attributes and will *not* remove any attributes from it. + + If *these* is an ordered dict (`dict` on Python 3.6+, + `collections.OrderedDict` otherwise), the order is deduced from + the order of the attributes inside *these*. Otherwise the order + of the definition of the attributes is used. + + :type these: `dict` of `str` to `attr.ib` + + :param str repr_ns: When using nested classes, there's no way in Python 2 + to automatically detect that. Therefore it's possible to set the + namespace explicitly for a more meaningful ``repr`` output. + :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*, + *order*, and *hash* arguments explicitly, assume they are set to + ``True`` **unless any** of the involved methods for one of the + arguments is implemented in the *current* class (i.e. it is *not* + inherited from some base class). + + So for example by implementing ``__eq__`` on a class yourself, + ``attrs`` will deduce ``eq=False`` and will create *neither* + ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible + ``__ne__`` by default, so it *should* be enough to only implement + ``__eq__`` in most cases). + + .. warning:: + + If you prevent ``attrs`` from creating the ordering methods for you + (``order=False``, e.g. by implementing ``__le__``), it becomes + *your* responsibility to make sure its ordering is sound. The best + way is to use the `functools.total_ordering` decorator. + + + Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*, + *cmp*, or *hash* overrides whatever *auto_detect* would determine. + + *auto_detect* requires Python 3. Setting it ``True`` on Python 2 raises + an `attrs.exceptions.PythonTooOldError`. + + :param bool repr: Create a ``__repr__`` method with a human readable + representation of ``attrs`` attributes.. + :param bool str: Create a ``__str__`` method that is identical to + ``__repr__``. This is usually not necessary except for + `Exception`\ s. + :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__`` + and ``__ne__`` methods that check two instances for equality. + + They compare the instances as if they were tuples of their ``attrs`` + attributes if and only if the types of both classes are *identical*! + :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``, + ``__gt__``, and ``__ge__`` methods that behave like *eq* above and + allow instances to be ordered. If ``None`` (default) mirror value of + *eq*. + :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* + and *order* to the same value. Must not be mixed with *eq* or *order*. + :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method + is generated according how *eq* and *frozen* are set. + + 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you. + 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to + None, marking it unhashable (which it is). + 3. If *eq* is False, ``__hash__`` will be left untouched meaning the + ``__hash__`` method of the base class will be used (if base class is + ``object``, this means it will fall back to id-based hashing.). + + Although not recommended, you can decide for yourself and force + ``attrs`` to create one (e.g. if the class is immutable even though you + didn't freeze it programmatically) by passing ``True`` or not. Both of + these cases are rather special and should be used carefully. + + See our documentation on `hashing`, Python's documentation on + `object.__hash__`, and the `GitHub issue that led to the default \ + behavior `_ for more + details. + :param bool init: Create a ``__init__`` method that initializes the + ``attrs`` attributes. Leading underscores are stripped for the argument + name. If a ``__attrs_pre_init__`` method exists on the class, it will + be called before the class is initialized. If a ``__attrs_post_init__`` + method exists on the class, it will be called after the class is fully + initialized. + + If ``init`` is ``False``, an ``__attrs_init__`` method will be + injected instead. This allows you to define a custom ``__init__`` + method that can do pre-init work such as ``super().__init__()``, + and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. + :param bool slots: Create a `slotted class ` that's more + memory-efficient. Slotted classes are generally superior to the default + dict classes, but have some gotchas you should know about, so we + encourage you to read the `glossary entry `. + :param bool frozen: Make instances immutable after initialization. If + someone attempts to modify a frozen instance, + `attr.exceptions.FrozenInstanceError` is raised. + + .. note:: + + 1. This is achieved by installing a custom ``__setattr__`` method + on your class, so you can't implement your own. + + 2. True immutability is impossible in Python. + + 3. This *does* have a minor a runtime performance `impact + ` when initializing new instances. In other words: + ``__init__`` is slightly slower with ``frozen=True``. + + 4. If a class is frozen, you cannot modify ``self`` in + ``__attrs_post_init__`` or a self-written ``__init__``. You can + circumvent that limitation by using + ``object.__setattr__(self, "attribute_name", value)``. + + 5. Subclasses of a frozen class are frozen too. + + :param bool weakref_slot: Make instances weak-referenceable. This has no + effect unless ``slots`` is also enabled. + :param bool auto_attribs: If ``True``, collect :pep:`526`-annotated + attributes (Python 3.6 and later only) from the class body. + + In this case, you **must** annotate every field. If ``attrs`` + encounters a field that is set to an `attr.ib` but lacks a type + annotation, an `attr.exceptions.UnannotatedAttributeError` is + raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't + want to set a type. + + If you assign a value to those attributes (e.g. ``x: int = 42``), that + value becomes the default value like if it were passed using + ``attr.ib(default=42)``. Passing an instance of `attrs.Factory` also + works as expected in most cases (see warning below). + + Attributes annotated as `typing.ClassVar`, and attributes that are + neither annotated nor set to an `attr.ib` are **ignored**. + + .. warning:: + For features that use the attribute name to create decorators (e.g. + `validators `), you still *must* assign `attr.ib` to + them. Otherwise Python will either not find the name or try to use + the default value to call e.g. ``validator`` on it. + + These errors can be quite confusing and probably the most common bug + report on our bug tracker. + + :param bool kw_only: Make all attributes keyword-only (Python 3+) + in the generated ``__init__`` (if ``init`` is ``False``, this + parameter is ignored). + :param bool cache_hash: Ensure that the object's hash code is computed + only once and stored on the object. If this is set to ``True``, + hashing must be either explicitly or implicitly enabled for this + class. If the hash code is cached, avoid any reassignments of + fields involved in hash code computation or mutations of the objects + those fields point to after object creation. If such changes occur, + the behavior of the object's hash code is undefined. + :param bool auto_exc: If the class subclasses `BaseException` + (which implicitly includes any subclass of any exception), the + following happens to behave like a well-behaved Python exceptions + class: + + - the values for *eq*, *order*, and *hash* are ignored and the + instances compare and hash by the instance's ids (N.B. ``attrs`` will + *not* remove existing implementations of ``__hash__`` or the equality + methods. It just won't add own ones.), + - all attributes that are either passed into ``__init__`` or have a + default value are additionally available as a tuple in the ``args`` + attribute, + - the value of *str* is ignored leaving ``__str__`` to base classes. + :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs`` + collects attributes from base classes. The default behavior is + incorrect in certain cases of multiple inheritance. It should be on by + default but is kept off for backward-compatibility. + + See issue `#428 `_ for + more details. + + :param Optional[bool] getstate_setstate: + .. note:: + This is usually only interesting for slotted classes and you should + probably just set *auto_detect* to `True`. + + If `True`, ``__getstate__`` and + ``__setstate__`` are generated and attached to the class. This is + necessary for slotted classes to be pickleable. If left `None`, it's + `True` by default for slotted classes and ``False`` for dict classes. + + If *auto_detect* is `True`, and *getstate_setstate* is left `None`, + and **either** ``__getstate__`` or ``__setstate__`` is detected directly + on the class (i.e. not inherited), it is set to `False` (this is usually + what you want). + + :param on_setattr: A callable that is run whenever the user attempts to set + an attribute (either by assignment like ``i.x = 42`` or by using + `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments + as validators: the instance, the attribute that is being modified, and + the new value. + + If no exception is raised, the attribute is set to the return value of + the callable. + + If a list of callables is passed, they're automatically wrapped in an + `attrs.setters.pipe`. + :type on_setattr: `callable`, or a list of callables, or `None`, or + `attrs.setters.NO_OP` + + :param Optional[callable] field_transformer: + A function that is called with the original class object and all + fields right before ``attrs`` finalizes the class. You can use + this, e.g., to automatically add converters or validators to + fields based on their types. See `transform-fields` for more details. + + :param bool match_args: + If `True` (default), set ``__match_args__`` on the class to support + :pep:`634` (Structural Pattern Matching). It is a tuple of all + non-keyword-only ``__init__`` parameter names on Python 3.10 and later. + Ignored on older Python versions. + + .. versionadded:: 16.0.0 *slots* + .. versionadded:: 16.1.0 *frozen* + .. versionadded:: 16.3.0 *str* + .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``. + .. versionchanged:: 17.1.0 + *hash* supports ``None`` as value which is also the default now. + .. versionadded:: 17.3.0 *auto_attribs* + .. versionchanged:: 18.1.0 + If *these* is passed, no attributes are deleted from the class body. + .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained. + .. versionadded:: 18.2.0 *weakref_slot* + .. deprecated:: 18.2.0 + ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a + `DeprecationWarning` if the classes compared are subclasses of + each other. ``__eq`` and ``__ne__`` never tried to compared subclasses + to each other. + .. versionchanged:: 19.2.0 + ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider + subclasses comparable anymore. + .. versionadded:: 18.2.0 *kw_only* + .. versionadded:: 18.2.0 *cache_hash* + .. versionadded:: 19.1.0 *auto_exc* + .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. + .. versionadded:: 19.2.0 *eq* and *order* + .. versionadded:: 20.1.0 *auto_detect* + .. versionadded:: 20.1.0 *collect_by_mro* + .. versionadded:: 20.1.0 *getstate_setstate* + .. versionadded:: 20.1.0 *on_setattr* + .. versionadded:: 20.3.0 *field_transformer* + .. versionchanged:: 21.1.0 + ``init=False`` injects ``__attrs_init__`` + .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` + .. versionchanged:: 21.1.0 *cmp* undeprecated + .. versionadded:: 21.3.0 *match_args* + """ + eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) + hash_ = hash # work around the lack of nonlocal + + if isinstance(on_setattr, (list, tuple)): + on_setattr = setters.pipe(*on_setattr) + + def wrap(cls): + is_frozen = frozen or _has_frozen_base_class(cls) + is_exc = auto_exc is True and issubclass(cls, BaseException) + has_own_setattr = auto_detect and _has_own_attribute( + cls, "__setattr__" + ) + + if has_own_setattr and is_frozen: + raise ValueError("Can't freeze a class with a custom __setattr__.") + + builder = _ClassBuilder( + cls, + these, + slots, + is_frozen, + weakref_slot, + _determine_whether_to_implement( + cls, + getstate_setstate, + auto_detect, + ("__getstate__", "__setstate__"), + default=slots, + ), + auto_attribs, + kw_only, + cache_hash, + is_exc, + collect_by_mro, + on_setattr, + has_own_setattr, + field_transformer, + ) + if _determine_whether_to_implement( + cls, repr, auto_detect, ("__repr__",) + ): + builder.add_repr(repr_ns) + if str is True: + builder.add_str() + + eq = _determine_whether_to_implement( + cls, eq_, auto_detect, ("__eq__", "__ne__") + ) + if not is_exc and eq is True: + builder.add_eq() + if not is_exc and _determine_whether_to_implement( + cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__") + ): + builder.add_order() + + builder.add_setattr() + + if ( + hash_ is None + and auto_detect is True + and _has_own_attribute(cls, "__hash__") + ): + hash = False + else: + hash = hash_ + if hash is not True and hash is not False and hash is not None: + # Can't use `hash in` because 1 == True for example. + raise TypeError( + "Invalid value for hash. Must be True, False, or None." + ) + elif hash is False or (hash is None and eq is False) or is_exc: + # Don't do anything. Should fall back to __object__'s __hash__ + # which is by id. + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " hashing must be either explicitly or implicitly " + "enabled." + ) + elif hash is True or ( + hash is None and eq is True and is_frozen is True + ): + # Build a __hash__ if told so, or if it's safe. + builder.add_hash() + else: + # Raise TypeError on attempts to hash. + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " hashing must be either explicitly or implicitly " + "enabled." + ) + builder.make_unhashable() + + if _determine_whether_to_implement( + cls, init, auto_detect, ("__init__",) + ): + builder.add_init() + else: + builder.add_attrs_init() + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " init must be True." + ) + + if ( + PY310 + and match_args + and not _has_own_attribute(cls, "__match_args__") + ): + builder.add_match_args() + + return builder.build_class() + + # maybe_cls's type depends on the usage of the decorator. It's a class + # if it's used as `@attrs` but ``None`` if used as `@attrs()`. + if maybe_cls is None: + return wrap + else: + return wrap(maybe_cls) + + +_attrs = attrs +""" +Internal alias so we can use it in functions that take an argument called +*attrs*. +""" + + +def _has_frozen_base_class(cls): + """ + Check whether *cls* has a frozen ancestor by looking at its + __setattr__. + """ + return cls.__setattr__ is _frozen_setattrs + + +def _generate_unique_filename(cls, func_name): + """ + Create a "filename" suitable for a function being generated. + """ + unique_filename = "".format( + func_name, + cls.__module__, + getattr(cls, "__qualname__", cls.__name__), + ) + return unique_filename + + +def _make_hash(cls, attrs, frozen, cache_hash): + attrs = tuple( + a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) + ) + + tab = " " + + unique_filename = _generate_unique_filename(cls, "hash") + type_hash = hash(unique_filename) + # If eq is custom generated, we need to include the functions in globs + globs = {} + + hash_def = "def __hash__(self" + hash_func = "hash((" + closing_braces = "))" + if not cache_hash: + hash_def += "):" + else: + hash_def += ", *" + + hash_def += ( + ", _cache_wrapper=" + + "__import__('attr._make')._make._CacheHashWrapper):" + ) + hash_func = "_cache_wrapper(" + hash_func + closing_braces += ")" + + method_lines = [hash_def] + + def append_hash_computation_lines(prefix, indent): + """ + Generate the code for actually computing the hash code. + Below this will either be returned directly or used to compute + a value which is then cached, depending on the value of cache_hash + """ + + method_lines.extend( + [ + indent + prefix + hash_func, + indent + " %d," % (type_hash,), + ] + ) + + for a in attrs: + if a.eq_key: + cmp_name = "_%s_key" % (a.name,) + globs[cmp_name] = a.eq_key + method_lines.append( + indent + " %s(self.%s)," % (cmp_name, a.name) + ) + else: + method_lines.append(indent + " self.%s," % a.name) + + method_lines.append(indent + " " + closing_braces) + + if cache_hash: + method_lines.append(tab + "if self.%s is None:" % _hash_cache_field) + if frozen: + append_hash_computation_lines( + "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2 + ) + method_lines.append(tab * 2 + ")") # close __setattr__ + else: + append_hash_computation_lines( + "self.%s = " % _hash_cache_field, tab * 2 + ) + method_lines.append(tab + "return self.%s" % _hash_cache_field) + else: + append_hash_computation_lines("return ", tab) + + script = "\n".join(method_lines) + return _make_method("__hash__", script, unique_filename, globs) + + +def _add_hash(cls, attrs): + """ + Add a hash method to *cls*. + """ + cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False) + return cls + + +def _make_ne(): + """ + Create __ne__ method. + """ + + def __ne__(self, other): + """ + Check equality and either forward a NotImplemented or + return the result negated. + """ + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + + return not result + + return __ne__ + + +def _make_eq(cls, attrs): + """ + Create __eq__ method for *cls* with *attrs*. + """ + attrs = [a for a in attrs if a.eq] + + unique_filename = _generate_unique_filename(cls, "eq") + lines = [ + "def __eq__(self, other):", + " if other.__class__ is not self.__class__:", + " return NotImplemented", + ] + + # We can't just do a big self.x = other.x and... clause due to + # irregularities like nan == nan is false but (nan,) == (nan,) is true. + globs = {} + if attrs: + lines.append(" return (") + others = [" ) == ("] + for a in attrs: + if a.eq_key: + cmp_name = "_%s_key" % (a.name,) + # Add the key function to the global namespace + # of the evaluated function. + globs[cmp_name] = a.eq_key + lines.append( + " %s(self.%s)," + % ( + cmp_name, + a.name, + ) + ) + others.append( + " %s(other.%s)," + % ( + cmp_name, + a.name, + ) + ) + else: + lines.append(" self.%s," % (a.name,)) + others.append(" other.%s," % (a.name,)) + + lines += others + [" )"] + else: + lines.append(" return True") + + script = "\n".join(lines) + + return _make_method("__eq__", script, unique_filename, globs) + + +def _make_order(cls, attrs): + """ + Create ordering methods for *cls* with *attrs*. + """ + attrs = [a for a in attrs if a.order] + + def attrs_to_tuple(obj): + """ + Save us some typing. + """ + return tuple( + key(value) if key else value + for value, key in ( + (getattr(obj, a.name), a.order_key) for a in attrs + ) + ) + + def __lt__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) < attrs_to_tuple(other) + + return NotImplemented + + def __le__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) <= attrs_to_tuple(other) + + return NotImplemented + + def __gt__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) > attrs_to_tuple(other) + + return NotImplemented + + def __ge__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) >= attrs_to_tuple(other) + + return NotImplemented + + return __lt__, __le__, __gt__, __ge__ + + +def _add_eq(cls, attrs=None): + """ + Add equality methods to *cls* with *attrs*. + """ + if attrs is None: + attrs = cls.__attrs_attrs__ + + cls.__eq__ = _make_eq(cls, attrs) + cls.__ne__ = _make_ne() + + return cls + + +if HAS_F_STRINGS: + + def _make_repr(attrs, ns, cls): + unique_filename = _generate_unique_filename(cls, "repr") + # Figure out which attributes to include, and which function to use to + # format them. The a.repr value can be either bool or a custom + # callable. + attr_names_with_reprs = tuple( + (a.name, (repr if a.repr is True else a.repr), a.init) + for a in attrs + if a.repr is not False + ) + globs = { + name + "_repr": r + for name, r, _ in attr_names_with_reprs + if r != repr + } + globs["_compat"] = _compat + globs["AttributeError"] = AttributeError + globs["NOTHING"] = NOTHING + attribute_fragments = [] + for name, r, i in attr_names_with_reprs: + accessor = ( + "self." + name + if i + else 'getattr(self, "' + name + '", NOTHING)' + ) + fragment = ( + "%s={%s!r}" % (name, accessor) + if r == repr + else "%s={%s_repr(%s)}" % (name, name, accessor) + ) + attribute_fragments.append(fragment) + repr_fragment = ", ".join(attribute_fragments) + + if ns is None: + cls_name_fragment = ( + '{self.__class__.__qualname__.rsplit(">.", 1)[-1]}' + ) + else: + cls_name_fragment = ns + ".{self.__class__.__name__}" + + lines = [ + "def __repr__(self):", + " try:", + " already_repring = _compat.repr_context.already_repring", + " except AttributeError:", + " already_repring = {id(self),}", + " _compat.repr_context.already_repring = already_repring", + " else:", + " if id(self) in already_repring:", + " return '...'", + " else:", + " already_repring.add(id(self))", + " try:", + " return f'%s(%s)'" % (cls_name_fragment, repr_fragment), + " finally:", + " already_repring.remove(id(self))", + ] + + return _make_method( + "__repr__", "\n".join(lines), unique_filename, globs=globs + ) + +else: + + def _make_repr(attrs, ns, _): + """ + Make a repr method that includes relevant *attrs*, adding *ns* to the + full name. + """ + + # Figure out which attributes to include, and which function to use to + # format them. The a.repr value can be either bool or a custom + # callable. + attr_names_with_reprs = tuple( + (a.name, repr if a.repr is True else a.repr) + for a in attrs + if a.repr is not False + ) + + def __repr__(self): + """ + Automatically created by attrs. + """ + try: + already_repring = _compat.repr_context.already_repring + except AttributeError: + already_repring = set() + _compat.repr_context.already_repring = already_repring + + if id(self) in already_repring: + return "..." + real_cls = self.__class__ + if ns is None: + class_name = real_cls.__qualname__.rsplit(">.", 1)[-1] + else: + class_name = ns + "." + real_cls.__name__ + + # Since 'self' remains on the stack (i.e.: strongly referenced) + # for the duration of this call, it's safe to depend on id(...) + # stability, and not need to track the instance and therefore + # worry about properties like weakref- or hash-ability. + already_repring.add(id(self)) + try: + result = [class_name, "("] + first = True + for name, attr_repr in attr_names_with_reprs: + if first: + first = False + else: + result.append(", ") + result.extend( + (name, "=", attr_repr(getattr(self, name, NOTHING))) + ) + return "".join(result) + ")" + finally: + already_repring.remove(id(self)) + + return __repr__ + + +def _add_repr(cls, ns=None, attrs=None): + """ + Add a repr method to *cls*. + """ + if attrs is None: + attrs = cls.__attrs_attrs__ + + cls.__repr__ = _make_repr(attrs, ns, cls) + return cls + + +def fields(cls): + """ + Return the tuple of ``attrs`` attributes for a class. + + The tuple also allows accessing the fields by their names (see below for + examples). + + :param type cls: Class to introspect. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + :rtype: tuple (with name accessors) of `attrs.Attribute` + + .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields + by name. + """ + if not isinstance(cls, type): + raise TypeError("Passed object must be a class.") + attrs = getattr(cls, "__attrs_attrs__", None) + if attrs is None: + raise NotAnAttrsClassError( + "{cls!r} is not an attrs-decorated class.".format(cls=cls) + ) + return attrs + + +def fields_dict(cls): + """ + Return an ordered dictionary of ``attrs`` attributes for a class, whose + keys are the attribute names. + + :param type cls: Class to introspect. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + :rtype: an ordered dict where keys are attribute names and values are + `attrs.Attribute`\\ s. This will be a `dict` if it's + naturally ordered like on Python 3.6+ or an + :class:`~collections.OrderedDict` otherwise. + + .. versionadded:: 18.1.0 + """ + if not isinstance(cls, type): + raise TypeError("Passed object must be a class.") + attrs = getattr(cls, "__attrs_attrs__", None) + if attrs is None: + raise NotAnAttrsClassError( + "{cls!r} is not an attrs-decorated class.".format(cls=cls) + ) + return ordered_dict((a.name, a) for a in attrs) + + +def validate(inst): + """ + Validate all attributes on *inst* that have a validator. + + Leaves all exceptions through. + + :param inst: Instance of a class with ``attrs`` attributes. + """ + if _config._run_validators is False: + return + + for a in fields(inst.__class__): + v = a.validator + if v is not None: + v(inst, a, getattr(inst, a.name)) + + +def _is_slot_cls(cls): + return "__slots__" in cls.__dict__ + + +def _is_slot_attr(a_name, base_attr_map): + """ + Check if the attribute name comes from a slot class. + """ + return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name]) + + +def _make_init( + cls, + attrs, + pre_init, + post_init, + frozen, + slots, + cache_hash, + base_attr_map, + is_exc, + cls_on_setattr, + attrs_init, +): + has_cls_on_setattr = ( + cls_on_setattr is not None and cls_on_setattr is not setters.NO_OP + ) + + if frozen and has_cls_on_setattr: + raise ValueError("Frozen classes can't use on_setattr.") + + needs_cached_setattr = cache_hash or frozen + filtered_attrs = [] + attr_dict = {} + for a in attrs: + if not a.init and a.default is NOTHING: + continue + + filtered_attrs.append(a) + attr_dict[a.name] = a + + if a.on_setattr is not None: + if frozen is True: + raise ValueError("Frozen classes can't use on_setattr.") + + needs_cached_setattr = True + elif has_cls_on_setattr and a.on_setattr is not setters.NO_OP: + needs_cached_setattr = True + + unique_filename = _generate_unique_filename(cls, "init") + + script, globs, annotations = _attrs_to_init_script( + filtered_attrs, + frozen, + slots, + pre_init, + post_init, + cache_hash, + base_attr_map, + is_exc, + has_cls_on_setattr, + attrs_init, + ) + if cls.__module__ in sys.modules: + # This makes typing.get_type_hints(CLS.__init__) resolve string types. + globs.update(sys.modules[cls.__module__].__dict__) + + globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) + + if needs_cached_setattr: + # Save the lookup overhead in __init__ if we need to circumvent + # setattr hooks. + globs["_setattr"] = _obj_setattr + + init = _make_method( + "__attrs_init__" if attrs_init else "__init__", + script, + unique_filename, + globs, + ) + init.__annotations__ = annotations + + return init + + +def _setattr(attr_name, value_var, has_on_setattr): + """ + Use the cached object.setattr to set *attr_name* to *value_var*. + """ + return "_setattr(self, '%s', %s)" % (attr_name, value_var) + + +def _setattr_with_converter(attr_name, value_var, has_on_setattr): + """ + Use the cached object.setattr to set *attr_name* to *value_var*, but run + its converter first. + """ + return "_setattr(self, '%s', %s(%s))" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + +def _assign(attr_name, value, has_on_setattr): + """ + Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise + relegate to _setattr. + """ + if has_on_setattr: + return _setattr(attr_name, value, True) + + return "self.%s = %s" % (attr_name, value) + + +def _assign_with_converter(attr_name, value_var, has_on_setattr): + """ + Unless *attr_name* has an on_setattr hook, use normal assignment after + conversion. Otherwise relegate to _setattr_with_converter. + """ + if has_on_setattr: + return _setattr_with_converter(attr_name, value_var, True) + + return "self.%s = %s(%s)" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + +def _attrs_to_init_script( + attrs, + frozen, + slots, + pre_init, + post_init, + cache_hash, + base_attr_map, + is_exc, + has_cls_on_setattr, + attrs_init, +): + """ + Return a script of an initializer for *attrs* and a dict of globals. + + The globals are expected by the generated script. + + If *frozen* is True, we cannot set the attributes directly so we use + a cached ``object.__setattr__``. + """ + lines = [] + if pre_init: + lines.append("self.__attrs_pre_init__()") + + if frozen is True: + if slots is True: + fmt_setter = _setattr + fmt_setter_with_converter = _setattr_with_converter + else: + # Dict frozen classes assign directly to __dict__. + # But only if the attribute doesn't come from an ancestor slot + # class. + # Note _inst_dict will be used again below if cache_hash is True + lines.append("_inst_dict = self.__dict__") + + def fmt_setter(attr_name, value_var, has_on_setattr): + if _is_slot_attr(attr_name, base_attr_map): + return _setattr(attr_name, value_var, has_on_setattr) + + return "_inst_dict['%s'] = %s" % (attr_name, value_var) + + def fmt_setter_with_converter( + attr_name, value_var, has_on_setattr + ): + if has_on_setattr or _is_slot_attr(attr_name, base_attr_map): + return _setattr_with_converter( + attr_name, value_var, has_on_setattr + ) + + return "_inst_dict['%s'] = %s(%s)" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + else: + # Not frozen. + fmt_setter = _assign + fmt_setter_with_converter = _assign_with_converter + + args = [] + kw_only_args = [] + attrs_to_validate = [] + + # This is a dictionary of names to validator and converter callables. + # Injecting this into __init__ globals lets us avoid lookups. + names_for_globals = {} + annotations = {"return": None} + + for a in attrs: + if a.validator: + attrs_to_validate.append(a) + + attr_name = a.name + has_on_setattr = a.on_setattr is not None or ( + a.on_setattr is not setters.NO_OP and has_cls_on_setattr + ) + arg_name = a.name.lstrip("_") + + has_factory = isinstance(a.default, Factory) + if has_factory and a.default.takes_self: + maybe_self = "self" + else: + maybe_self = "" + + if a.init is False: + if has_factory: + init_factory_name = _init_factory_pat.format(a.name) + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, + init_factory_name + "(%s)" % (maybe_self,), + has_on_setattr, + ) + ) + conv_name = _init_converter_pat % (a.name,) + names_for_globals[conv_name] = a.converter + else: + lines.append( + fmt_setter( + attr_name, + init_factory_name + "(%s)" % (maybe_self,), + has_on_setattr, + ) + ) + names_for_globals[init_factory_name] = a.default.factory + else: + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, + "attr_dict['%s'].default" % (attr_name,), + has_on_setattr, + ) + ) + conv_name = _init_converter_pat % (a.name,) + names_for_globals[conv_name] = a.converter + else: + lines.append( + fmt_setter( + attr_name, + "attr_dict['%s'].default" % (attr_name,), + has_on_setattr, + ) + ) + elif a.default is not NOTHING and not has_factory: + arg = "%s=attr_dict['%s'].default" % (arg_name, attr_name) + if a.kw_only: + kw_only_args.append(arg) + else: + args.append(arg) + + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) + + elif has_factory: + arg = "%s=NOTHING" % (arg_name,) + if a.kw_only: + kw_only_args.append(arg) + else: + args.append(arg) + lines.append("if %s is not NOTHING:" % (arg_name,)) + + init_factory_name = _init_factory_pat.format(a.name) + if a.converter is not None: + lines.append( + " " + + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + lines.append("else:") + lines.append( + " " + + fmt_setter_with_converter( + attr_name, + init_factory_name + "(" + maybe_self + ")", + has_on_setattr, + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append( + " " + fmt_setter(attr_name, arg_name, has_on_setattr) + ) + lines.append("else:") + lines.append( + " " + + fmt_setter( + attr_name, + init_factory_name + "(" + maybe_self + ")", + has_on_setattr, + ) + ) + names_for_globals[init_factory_name] = a.default.factory + else: + if a.kw_only: + kw_only_args.append(arg_name) + else: + args.append(arg_name) + + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) + + if a.init is True: + if a.type is not None and a.converter is None: + annotations[arg_name] = a.type + elif a.converter is not None: + # Try to get the type from the converter. + t = _AnnotationExtractor(a.converter).get_first_param_type() + if t: + annotations[arg_name] = t + + if attrs_to_validate: # we can skip this if there are no validators. + names_for_globals["_config"] = _config + lines.append("if _config._run_validators is True:") + for a in attrs_to_validate: + val_name = "__attr_validator_" + a.name + attr_name = "__attr_" + a.name + lines.append( + " %s(self, %s, self.%s)" % (val_name, attr_name, a.name) + ) + names_for_globals[val_name] = a.validator + names_for_globals[attr_name] = a + + if post_init: + lines.append("self.__attrs_post_init__()") + + # because this is set only after __attrs_post_init__ is called, a crash + # will result if post-init tries to access the hash code. This seemed + # preferable to setting this beforehand, in which case alteration to + # field values during post-init combined with post-init accessing the + # hash code would result in silent bugs. + if cache_hash: + if frozen: + if slots: + # if frozen and slots, then _setattr defined above + init_hash_cache = "_setattr(self, '%s', %s)" + else: + # if frozen and not slots, then _inst_dict defined above + init_hash_cache = "_inst_dict['%s'] = %s" + else: + init_hash_cache = "self.%s = %s" + lines.append(init_hash_cache % (_hash_cache_field, "None")) + + # For exceptions we rely on BaseException.__init__ for proper + # initialization. + if is_exc: + vals = ",".join("self." + a.name for a in attrs if a.init) + + lines.append("BaseException.__init__(self, %s)" % (vals,)) + + args = ", ".join(args) + if kw_only_args: + args += "%s*, %s" % ( + ", " if args else "", # leading comma + ", ".join(kw_only_args), # kw_only args + ) + return ( + """\ +def {init_name}(self, {args}): + {lines} +""".format( + init_name=("__attrs_init__" if attrs_init else "__init__"), + args=args, + lines="\n ".join(lines) if lines else "pass", + ), + names_for_globals, + annotations, + ) + + +class Attribute: + """ + *Read-only* representation of an attribute. + + The class has *all* arguments of `attr.ib` (except for ``factory`` + which is only syntactic sugar for ``default=Factory(...)`` plus the + following: + + - ``name`` (`str`): The name of the attribute. + - ``inherited`` (`bool`): Whether or not that attribute has been inherited + from a base class. + - ``eq_key`` and ``order_key`` (`typing.Callable` or `None`): The callables + that are used for comparing and ordering objects by this attribute, + respectively. These are set by passing a callable to `attr.ib`'s ``eq``, + ``order``, or ``cmp`` arguments. See also :ref:`comparison customization + `. + + Instances of this class are frequently used for introspection purposes + like: + + - `fields` returns a tuple of them. + - Validators get them passed as the first argument. + - The :ref:`field transformer ` hook receives a list of + them. + + .. versionadded:: 20.1.0 *inherited* + .. versionadded:: 20.1.0 *on_setattr* + .. versionchanged:: 20.2.0 *inherited* is not taken into account for + equality checks and hashing anymore. + .. versionadded:: 21.1.0 *eq_key* and *order_key* + + For the full version history of the fields, see `attr.ib`. + """ + + __slots__ = ( + "name", + "default", + "validator", + "repr", + "eq", + "eq_key", + "order", + "order_key", + "hash", + "init", + "metadata", + "type", + "converter", + "kw_only", + "inherited", + "on_setattr", + ) + + def __init__( + self, + name, + default, + validator, + repr, + cmp, # XXX: unused, remove along with other cmp code. + hash, + init, + inherited, + metadata=None, + type=None, + converter=None, + kw_only=False, + eq=None, + eq_key=None, + order=None, + order_key=None, + on_setattr=None, + ): + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq_key or eq, order_key or order, True + ) + + # Cache this descriptor here to speed things up later. + bound_setattr = _obj_setattr.__get__(self, Attribute) + + # Despite the big red warning, people *do* instantiate `Attribute` + # themselves. + bound_setattr("name", name) + bound_setattr("default", default) + bound_setattr("validator", validator) + bound_setattr("repr", repr) + bound_setattr("eq", eq) + bound_setattr("eq_key", eq_key) + bound_setattr("order", order) + bound_setattr("order_key", order_key) + bound_setattr("hash", hash) + bound_setattr("init", init) + bound_setattr("converter", converter) + bound_setattr( + "metadata", + ( + types.MappingProxyType(dict(metadata)) # Shallow copy + if metadata + else _empty_metadata_singleton + ), + ) + bound_setattr("type", type) + bound_setattr("kw_only", kw_only) + bound_setattr("inherited", inherited) + bound_setattr("on_setattr", on_setattr) + + def __setattr__(self, name, value): + raise FrozenInstanceError() + + @classmethod + def from_counting_attr(cls, name, ca, type=None): + # type holds the annotated value. deal with conflicts: + if type is None: + type = ca.type + elif ca.type is not None: + raise ValueError( + "Type annotation and type argument cannot both be present" + ) + inst_dict = { + k: getattr(ca, k) + for k in Attribute.__slots__ + if k + not in ( + "name", + "validator", + "default", + "type", + "inherited", + ) # exclude methods and deprecated alias + } + return cls( + name=name, + validator=ca._validator, + default=ca._default, + type=type, + cmp=None, + inherited=False, + **inst_dict + ) + + # Don't use attr.evolve since fields(Attribute) doesn't work + def evolve(self, **changes): + """ + Copy *self* and apply *changes*. + + This works similarly to `attr.evolve` but that function does not work + with ``Attribute``. + + It is mainly meant to be used for `transform-fields`. + + .. versionadded:: 20.3.0 + """ + new = copy.copy(self) + + new._setattrs(changes.items()) + + return new + + # Don't use _add_pickle since fields(Attribute) doesn't work + def __getstate__(self): + """ + Play nice with pickle. + """ + return tuple( + getattr(self, name) if name != "metadata" else dict(self.metadata) + for name in self.__slots__ + ) + + def __setstate__(self, state): + """ + Play nice with pickle. + """ + self._setattrs(zip(self.__slots__, state)) + + def _setattrs(self, name_values_pairs): + bound_setattr = _obj_setattr.__get__(self, Attribute) + for name, value in name_values_pairs: + if name != "metadata": + bound_setattr(name, value) + else: + bound_setattr( + name, + types.MappingProxyType(dict(value)) + if value + else _empty_metadata_singleton, + ) + + +_a = [ + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + eq=True, + order=False, + hash=(name != "metadata"), + init=True, + inherited=False, + ) + for name in Attribute.__slots__ +] + +Attribute = _add_hash( + _add_eq( + _add_repr(Attribute, attrs=_a), + attrs=[a for a in _a if a.name != "inherited"], + ), + attrs=[a for a in _a if a.hash and a.name != "inherited"], +) + + +class _CountingAttr: + """ + Intermediate representation of attributes that uses a counter to preserve + the order in which the attributes have been defined. + + *Internal* data structure of the attrs library. Running into is most + likely the result of a bug like a forgotten `@attr.s` decorator. + """ + + __slots__ = ( + "counter", + "_default", + "repr", + "eq", + "eq_key", + "order", + "order_key", + "hash", + "init", + "metadata", + "_validator", + "converter", + "type", + "kw_only", + "on_setattr", + ) + __attrs_attrs__ = tuple( + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + hash=True, + init=True, + kw_only=False, + eq=True, + eq_key=None, + order=False, + order_key=None, + inherited=False, + on_setattr=None, + ) + for name in ( + "counter", + "_default", + "repr", + "eq", + "order", + "hash", + "init", + "on_setattr", + ) + ) + ( + Attribute( + name="metadata", + default=None, + validator=None, + repr=True, + cmp=None, + hash=False, + init=True, + kw_only=False, + eq=True, + eq_key=None, + order=False, + order_key=None, + inherited=False, + on_setattr=None, + ), + ) + cls_counter = 0 + + def __init__( + self, + default, + validator, + repr, + cmp, + hash, + init, + converter, + metadata, + type, + kw_only, + eq, + eq_key, + order, + order_key, + on_setattr, + ): + _CountingAttr.cls_counter += 1 + self.counter = _CountingAttr.cls_counter + self._default = default + self._validator = validator + self.converter = converter + self.repr = repr + self.eq = eq + self.eq_key = eq_key + self.order = order + self.order_key = order_key + self.hash = hash + self.init = init + self.metadata = metadata + self.type = type + self.kw_only = kw_only + self.on_setattr = on_setattr + + def validator(self, meth): + """ + Decorator that adds *meth* to the list of validators. + + Returns *meth* unchanged. + + .. versionadded:: 17.1.0 + """ + if self._validator is None: + self._validator = meth + else: + self._validator = and_(self._validator, meth) + return meth + + def default(self, meth): + """ + Decorator that allows to set the default for an attribute. + + Returns *meth* unchanged. + + :raises DefaultAlreadySetError: If default has been set before. + + .. versionadded:: 17.1.0 + """ + if self._default is not NOTHING: + raise DefaultAlreadySetError() + + self._default = Factory(meth, takes_self=True) + + return meth + + +_CountingAttr = _add_eq(_add_repr(_CountingAttr)) + + +class Factory: + """ + Stores a factory callable. + + If passed as the default value to `attrs.field`, the factory is used to + generate a new value. + + :param callable factory: A callable that takes either none or exactly one + mandatory positional argument depending on *takes_self*. + :param bool takes_self: Pass the partially initialized instance that is + being initialized as a positional argument. + + .. versionadded:: 17.1.0 *takes_self* + """ + + __slots__ = ("factory", "takes_self") + + def __init__(self, factory, takes_self=False): + """ + `Factory` is part of the default machinery so if we want a default + value here, we have to implement it ourselves. + """ + self.factory = factory + self.takes_self = takes_self + + def __getstate__(self): + """ + Play nice with pickle. + """ + return tuple(getattr(self, name) for name in self.__slots__) + + def __setstate__(self, state): + """ + Play nice with pickle. + """ + for name, value in zip(self.__slots__, state): + setattr(self, name, value) + + +_f = [ + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + eq=True, + order=False, + hash=True, + init=True, + inherited=False, + ) + for name in Factory.__slots__ +] + +Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) + + +def make_class(name, attrs, bases=(object,), **attributes_arguments): + """ + A quick way to create a new class called *name* with *attrs*. + + :param str name: The name for the new class. + + :param attrs: A list of names or a dictionary of mappings of names to + attributes. + + If *attrs* is a list or an ordered dict (`dict` on Python 3.6+, + `collections.OrderedDict` otherwise), the order is deduced from + the order of the names or attributes inside *attrs*. Otherwise the + order of the definition of the attributes is used. + :type attrs: `list` or `dict` + + :param tuple bases: Classes that the new class will subclass. + + :param attributes_arguments: Passed unmodified to `attr.s`. + + :return: A new class with *attrs*. + :rtype: type + + .. versionadded:: 17.1.0 *bases* + .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. + """ + if isinstance(attrs, dict): + cls_dict = attrs + elif isinstance(attrs, (list, tuple)): + cls_dict = {a: attrib() for a in attrs} + else: + raise TypeError("attrs argument must be a dict or a list.") + + pre_init = cls_dict.pop("__attrs_pre_init__", None) + post_init = cls_dict.pop("__attrs_post_init__", None) + user_init = cls_dict.pop("__init__", None) + + body = {} + if pre_init is not None: + body["__attrs_pre_init__"] = pre_init + if post_init is not None: + body["__attrs_post_init__"] = post_init + if user_init is not None: + body["__init__"] = user_init + + type_ = types.new_class(name, bases, {}, lambda ns: ns.update(body)) + + # For pickling to work, the __module__ variable needs to be set to the + # frame where the class is created. Bypass this step in environments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + type_.__module__ = sys._getframe(1).f_globals.get( + "__name__", "__main__" + ) + except (AttributeError, ValueError): + pass + + # We do it here for proper warnings with meaningful stacklevel. + cmp = attributes_arguments.pop("cmp", None) + ( + attributes_arguments["eq"], + attributes_arguments["order"], + ) = _determine_attrs_eq_order( + cmp, + attributes_arguments.get("eq"), + attributes_arguments.get("order"), + True, + ) + + return _attrs(these=cls_dict, **attributes_arguments)(type_) + + +# These are required by within this module so we define them here and merely +# import into .validators / .converters. + + +@attrs(slots=True, hash=True) +class _AndValidator: + """ + Compose many validators to a single one. + """ + + _validators = attrib() + + def __call__(self, inst, attr, value): + for v in self._validators: + v(inst, attr, value) + + +def and_(*validators): + """ + A validator that composes multiple validators into one. + + When called on a value, it runs all wrapped validators. + + :param callables validators: Arbitrary number of validators. + + .. versionadded:: 17.1.0 + """ + vals = [] + for validator in validators: + vals.extend( + validator._validators + if isinstance(validator, _AndValidator) + else [validator] + ) + + return _AndValidator(tuple(vals)) + + +def pipe(*converters): + """ + A converter that composes multiple converters into one. + + When called on a value, it runs all wrapped converters, returning the + *last* value. + + Type annotations will be inferred from the wrapped converters', if + they have any. + + :param callables converters: Arbitrary number of converters. + + .. versionadded:: 20.1.0 + """ + + def pipe_converter(val): + for converter in converters: + val = converter(val) + + return val + + if not converters: + # If the converter list is empty, pipe_converter is the identity. + A = typing.TypeVar("A") + pipe_converter.__annotations__ = {"val": A, "return": A} + else: + # Get parameter type from first converter. + t = _AnnotationExtractor(converters[0]).get_first_param_type() + if t: + pipe_converter.__annotations__["val"] = t + + # Get return type from last converter. + rt = _AnnotationExtractor(converters[-1]).get_return_type() + if rt: + pipe_converter.__annotations__["return"] = rt + + return pipe_converter diff --git a/axios-example/lib/python3.10/site-packages/attr/_next_gen.py b/axios-example/lib/python3.10/site-packages/attr/_next_gen.py new file mode 100644 index 0000000..5a06a74 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_next_gen.py @@ -0,0 +1,220 @@ +# SPDX-License-Identifier: MIT + +""" +These are Python 3.6+-only and keyword-only APIs that call `attr.s` and +`attr.ib` with different default values. +""" + + +from functools import partial + +from . import setters +from ._funcs import asdict as _asdict +from ._funcs import astuple as _astuple +from ._make import ( + NOTHING, + _frozen_setattrs, + _ng_default_on_setattr, + attrib, + attrs, +) +from .exceptions import UnannotatedAttributeError + + +def define( + maybe_cls=None, + *, + these=None, + repr=None, + hash=None, + init=None, + slots=True, + frozen=False, + weakref_slot=True, + str=False, + auto_attribs=None, + kw_only=False, + cache_hash=False, + auto_exc=True, + eq=None, + order=False, + auto_detect=True, + getstate_setstate=None, + on_setattr=None, + field_transformer=None, + match_args=True, +): + r""" + Define an ``attrs`` class. + + Differences to the classic `attr.s` that it uses underneath: + + - Automatically detect whether or not *auto_attribs* should be `True` (c.f. + *auto_attribs* parameter). + - If *frozen* is `False`, run converters and validators when setting an + attribute by default. + - *slots=True* + + .. caution:: + + Usually this has only upsides and few visible effects in everyday + programming. But it *can* lead to some suprising behaviors, so please + make sure to read :term:`slotted classes`. + - *auto_exc=True* + - *auto_detect=True* + - *order=False* + - Some options that were only relevant on Python 2 or were kept around for + backwards-compatibility have been removed. + + Please note that these are all defaults and you can change them as you + wish. + + :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves + exactly like `attr.s`. If left `None`, `attr.s` will try to guess: + + 1. If any attributes are annotated and no unannotated `attrs.fields`\ s + are found, it assumes *auto_attribs=True*. + 2. Otherwise it assumes *auto_attribs=False* and tries to collect + `attrs.fields`\ s. + + For now, please refer to `attr.s` for the rest of the parameters. + + .. versionadded:: 20.1.0 + .. versionchanged:: 21.3.0 Converters are also run ``on_setattr``. + """ + + def do_it(cls, auto_attribs): + return attrs( + maybe_cls=cls, + these=these, + repr=repr, + hash=hash, + init=init, + slots=slots, + frozen=frozen, + weakref_slot=weakref_slot, + str=str, + auto_attribs=auto_attribs, + kw_only=kw_only, + cache_hash=cache_hash, + auto_exc=auto_exc, + eq=eq, + order=order, + auto_detect=auto_detect, + collect_by_mro=True, + getstate_setstate=getstate_setstate, + on_setattr=on_setattr, + field_transformer=field_transformer, + match_args=match_args, + ) + + def wrap(cls): + """ + Making this a wrapper ensures this code runs during class creation. + + We also ensure that frozen-ness of classes is inherited. + """ + nonlocal frozen, on_setattr + + had_on_setattr = on_setattr not in (None, setters.NO_OP) + + # By default, mutable classes convert & validate on setattr. + if frozen is False and on_setattr is None: + on_setattr = _ng_default_on_setattr + + # However, if we subclass a frozen class, we inherit the immutability + # and disable on_setattr. + for base_cls in cls.__bases__: + if base_cls.__setattr__ is _frozen_setattrs: + if had_on_setattr: + raise ValueError( + "Frozen classes can't use on_setattr " + "(frozen-ness was inherited)." + ) + + on_setattr = setters.NO_OP + break + + if auto_attribs is not None: + return do_it(cls, auto_attribs) + + try: + return do_it(cls, True) + except UnannotatedAttributeError: + return do_it(cls, False) + + # maybe_cls's type depends on the usage of the decorator. It's a class + # if it's used as `@attrs` but ``None`` if used as `@attrs()`. + if maybe_cls is None: + return wrap + else: + return wrap(maybe_cls) + + +mutable = define +frozen = partial(define, frozen=True, on_setattr=None) + + +def field( + *, + default=NOTHING, + validator=None, + repr=True, + hash=None, + init=True, + metadata=None, + converter=None, + factory=None, + kw_only=False, + eq=None, + order=None, + on_setattr=None, +): + """ + Identical to `attr.ib`, except keyword-only and with some arguments + removed. + + .. versionadded:: 20.1.0 + """ + return attrib( + default=default, + validator=validator, + repr=repr, + hash=hash, + init=init, + metadata=metadata, + converter=converter, + factory=factory, + kw_only=kw_only, + eq=eq, + order=order, + on_setattr=on_setattr, + ) + + +def asdict(inst, *, recurse=True, filter=None, value_serializer=None): + """ + Same as `attr.asdict`, except that collections types are always retained + and dict is always used as *dict_factory*. + + .. versionadded:: 21.3.0 + """ + return _asdict( + inst=inst, + recurse=recurse, + filter=filter, + value_serializer=value_serializer, + retain_collection_types=True, + ) + + +def astuple(inst, *, recurse=True, filter=None): + """ + Same as `attr.astuple`, except that collections types are always retained + and `tuple` is always used as the *tuple_factory*. + + .. versionadded:: 21.3.0 + """ + return _astuple( + inst=inst, recurse=recurse, filter=filter, retain_collection_types=True + ) diff --git a/axios-example/lib/python3.10/site-packages/attr/_version_info.py b/axios-example/lib/python3.10/site-packages/attr/_version_info.py new file mode 100644 index 0000000..51a1312 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_version_info.py @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: MIT + + +from functools import total_ordering + +from ._funcs import astuple +from ._make import attrib, attrs + + +@total_ordering +@attrs(eq=False, order=False, slots=True, frozen=True) +class VersionInfo: + """ + A version object that can be compared to tuple of length 1--4: + + >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) + True + >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) + True + >>> vi = attr.VersionInfo(19, 2, 0, "final") + >>> vi < (19, 1, 1) + False + >>> vi < (19,) + False + >>> vi == (19, 2,) + True + >>> vi == (19, 2, 1) + False + + .. versionadded:: 19.2 + """ + + year = attrib(type=int) + minor = attrib(type=int) + micro = attrib(type=int) + releaselevel = attrib(type=str) + + @classmethod + def _from_version_string(cls, s): + """ + Parse *s* and return a _VersionInfo. + """ + v = s.split(".") + if len(v) == 3: + v.append("final") + + return cls( + year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] + ) + + def _ensure_tuple(self, other): + """ + Ensure *other* is a tuple of a valid length. + + Returns a possibly transformed *other* and ourselves as a tuple of + the same length as *other*. + """ + + if self.__class__ is other.__class__: + other = astuple(other) + + if not isinstance(other, tuple): + raise NotImplementedError + + if not (1 <= len(other) <= 4): + raise NotImplementedError + + return astuple(self)[: len(other)], other + + def __eq__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + return us == them + + def __lt__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't + # have to do anything special with releaselevel for now. + return us < them diff --git a/axios-example/lib/python3.10/site-packages/attr/_version_info.pyi b/axios-example/lib/python3.10/site-packages/attr/_version_info.pyi new file mode 100644 index 0000000..45ced08 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/_version_info.pyi @@ -0,0 +1,9 @@ +class VersionInfo: + @property + def year(self) -> int: ... + @property + def minor(self) -> int: ... + @property + def micro(self) -> int: ... + @property + def releaselevel(self) -> str: ... diff --git a/axios-example/lib/python3.10/site-packages/attr/converters.py b/axios-example/lib/python3.10/site-packages/attr/converters.py new file mode 100644 index 0000000..a73626c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/converters.py @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: MIT + +""" +Commonly useful converters. +""" + + +import typing + +from ._compat import _AnnotationExtractor +from ._make import NOTHING, Factory, pipe + + +__all__ = [ + "default_if_none", + "optional", + "pipe", + "to_bool", +] + + +def optional(converter): + """ + A converter that allows an attribute to be optional. An optional attribute + is one which can be set to ``None``. + + Type annotations will be inferred from the wrapped converter's, if it + has any. + + :param callable converter: the converter that is used for non-``None`` + values. + + .. versionadded:: 17.1.0 + """ + + def optional_converter(val): + if val is None: + return None + return converter(val) + + xtr = _AnnotationExtractor(converter) + + t = xtr.get_first_param_type() + if t: + optional_converter.__annotations__["val"] = typing.Optional[t] + + rt = xtr.get_return_type() + if rt: + optional_converter.__annotations__["return"] = typing.Optional[rt] + + return optional_converter + + +def default_if_none(default=NOTHING, factory=None): + """ + A converter that allows to replace ``None`` values by *default* or the + result of *factory*. + + :param default: Value to be used if ``None`` is passed. Passing an instance + of `attrs.Factory` is supported, however the ``takes_self`` option + is *not*. + :param callable factory: A callable that takes no parameters whose result + is used if ``None`` is passed. + + :raises TypeError: If **neither** *default* or *factory* is passed. + :raises TypeError: If **both** *default* and *factory* are passed. + :raises ValueError: If an instance of `attrs.Factory` is passed with + ``takes_self=True``. + + .. versionadded:: 18.2.0 + """ + if default is NOTHING and factory is None: + raise TypeError("Must pass either `default` or `factory`.") + + if default is not NOTHING and factory is not None: + raise TypeError( + "Must pass either `default` or `factory` but not both." + ) + + if factory is not None: + default = Factory(factory) + + if isinstance(default, Factory): + if default.takes_self: + raise ValueError( + "`takes_self` is not supported by default_if_none." + ) + + def default_if_none_converter(val): + if val is not None: + return val + + return default.factory() + + else: + + def default_if_none_converter(val): + if val is not None: + return val + + return default + + return default_if_none_converter + + +def to_bool(val): + """ + Convert "boolean" strings (e.g., from env. vars.) to real booleans. + + Values mapping to :code:`True`: + + - :code:`True` + - :code:`"true"` / :code:`"t"` + - :code:`"yes"` / :code:`"y"` + - :code:`"on"` + - :code:`"1"` + - :code:`1` + + Values mapping to :code:`False`: + + - :code:`False` + - :code:`"false"` / :code:`"f"` + - :code:`"no"` / :code:`"n"` + - :code:`"off"` + - :code:`"0"` + - :code:`0` + + :raises ValueError: for any other value. + + .. versionadded:: 21.3.0 + """ + if isinstance(val, str): + val = val.lower() + truthy = {True, "true", "t", "yes", "y", "on", "1", 1} + falsy = {False, "false", "f", "no", "n", "off", "0", 0} + try: + if val in truthy: + return True + if val in falsy: + return False + except TypeError: + # Raised when "val" is not hashable (e.g., lists) + pass + raise ValueError("Cannot convert value to bool: {}".format(val)) diff --git a/axios-example/lib/python3.10/site-packages/attr/converters.pyi b/axios-example/lib/python3.10/site-packages/attr/converters.pyi new file mode 100644 index 0000000..0f58088 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/converters.pyi @@ -0,0 +1,13 @@ +from typing import Callable, Optional, TypeVar, overload + +from . import _ConverterType + +_T = TypeVar("_T") + +def pipe(*validators: _ConverterType) -> _ConverterType: ... +def optional(converter: _ConverterType) -> _ConverterType: ... +@overload +def default_if_none(default: _T) -> _ConverterType: ... +@overload +def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ... +def to_bool(val: str) -> bool: ... diff --git a/axios-example/lib/python3.10/site-packages/attr/exceptions.py b/axios-example/lib/python3.10/site-packages/attr/exceptions.py new file mode 100644 index 0000000..5dc51e0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/exceptions.py @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: MIT + + +class FrozenError(AttributeError): + """ + A frozen/immutable instance or attribute have been attempted to be + modified. + + It mirrors the behavior of ``namedtuples`` by using the same error message + and subclassing `AttributeError`. + + .. versionadded:: 20.1.0 + """ + + msg = "can't set attribute" + args = [msg] + + +class FrozenInstanceError(FrozenError): + """ + A frozen instance has been attempted to be modified. + + .. versionadded:: 16.1.0 + """ + + +class FrozenAttributeError(FrozenError): + """ + A frozen attribute has been attempted to be modified. + + .. versionadded:: 20.1.0 + """ + + +class AttrsAttributeNotFoundError(ValueError): + """ + An ``attrs`` function couldn't find an attribute that the user asked for. + + .. versionadded:: 16.2.0 + """ + + +class NotAnAttrsClassError(ValueError): + """ + A non-``attrs`` class has been passed into an ``attrs`` function. + + .. versionadded:: 16.2.0 + """ + + +class DefaultAlreadySetError(RuntimeError): + """ + A default has been set using ``attr.ib()`` and is attempted to be reset + using the decorator. + + .. versionadded:: 17.1.0 + """ + + +class UnannotatedAttributeError(RuntimeError): + """ + A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type + annotation. + + .. versionadded:: 17.3.0 + """ + + +class PythonTooOldError(RuntimeError): + """ + It was attempted to use an ``attrs`` feature that requires a newer Python + version. + + .. versionadded:: 18.2.0 + """ + + +class NotCallableError(TypeError): + """ + A ``attr.ib()`` requiring a callable has been set with a value + that is not callable. + + .. versionadded:: 19.2.0 + """ + + def __init__(self, msg, value): + super(TypeError, self).__init__(msg, value) + self.msg = msg + self.value = value + + def __str__(self): + return str(self.msg) diff --git a/axios-example/lib/python3.10/site-packages/attr/exceptions.pyi b/axios-example/lib/python3.10/site-packages/attr/exceptions.pyi new file mode 100644 index 0000000..f268011 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/exceptions.pyi @@ -0,0 +1,17 @@ +from typing import Any + +class FrozenError(AttributeError): + msg: str = ... + +class FrozenInstanceError(FrozenError): ... +class FrozenAttributeError(FrozenError): ... +class AttrsAttributeNotFoundError(ValueError): ... +class NotAnAttrsClassError(ValueError): ... +class DefaultAlreadySetError(RuntimeError): ... +class UnannotatedAttributeError(RuntimeError): ... +class PythonTooOldError(RuntimeError): ... + +class NotCallableError(TypeError): + msg: str = ... + value: Any = ... + def __init__(self, msg: str, value: Any) -> None: ... diff --git a/axios-example/lib/python3.10/site-packages/attr/filters.py b/axios-example/lib/python3.10/site-packages/attr/filters.py new file mode 100644 index 0000000..baa25e9 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/filters.py @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: MIT + +""" +Commonly useful filters for `attr.asdict`. +""" + +from ._make import Attribute + + +def _split_what(what): + """ + Returns a tuple of `frozenset`s of classes and attributes. + """ + return ( + frozenset(cls for cls in what if isinstance(cls, type)), + frozenset(cls for cls in what if isinstance(cls, Attribute)), + ) + + +def include(*what): + """ + Include *what*. + + :param what: What to include. + :type what: `list` of `type` or `attrs.Attribute`\\ s + + :rtype: `callable` + """ + cls, attrs = _split_what(what) + + def include_(attribute, value): + return value.__class__ in cls or attribute in attrs + + return include_ + + +def exclude(*what): + """ + Exclude *what*. + + :param what: What to exclude. + :type what: `list` of classes or `attrs.Attribute`\\ s. + + :rtype: `callable` + """ + cls, attrs = _split_what(what) + + def exclude_(attribute, value): + return value.__class__ not in cls and attribute not in attrs + + return exclude_ diff --git a/axios-example/lib/python3.10/site-packages/attr/filters.pyi b/axios-example/lib/python3.10/site-packages/attr/filters.pyi new file mode 100644 index 0000000..9938668 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/filters.pyi @@ -0,0 +1,6 @@ +from typing import Any, Union + +from . import Attribute, _FilterType + +def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... +def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... diff --git a/axios-example/lib/python3.10/site-packages/attr/py.typed b/axios-example/lib/python3.10/site-packages/attr/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/attr/setters.py b/axios-example/lib/python3.10/site-packages/attr/setters.py new file mode 100644 index 0000000..12ed675 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/setters.py @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: MIT + +""" +Commonly used hooks for on_setattr. +""" + + +from . import _config +from .exceptions import FrozenAttributeError + + +def pipe(*setters): + """ + Run all *setters* and return the return value of the last one. + + .. versionadded:: 20.1.0 + """ + + def wrapped_pipe(instance, attrib, new_value): + rv = new_value + + for setter in setters: + rv = setter(instance, attrib, rv) + + return rv + + return wrapped_pipe + + +def frozen(_, __, ___): + """ + Prevent an attribute to be modified. + + .. versionadded:: 20.1.0 + """ + raise FrozenAttributeError() + + +def validate(instance, attrib, new_value): + """ + Run *attrib*'s validator on *new_value* if it has one. + + .. versionadded:: 20.1.0 + """ + if _config._run_validators is False: + return new_value + + v = attrib.validator + if not v: + return new_value + + v(instance, attrib, new_value) + + return new_value + + +def convert(instance, attrib, new_value): + """ + Run *attrib*'s converter -- if it has one -- on *new_value* and return the + result. + + .. versionadded:: 20.1.0 + """ + c = attrib.converter + if c: + return c(new_value) + + return new_value + + +# Sentinel for disabling class-wide *on_setattr* hooks for certain attributes. +# autodata stopped working, so the docstring is inlined in the API docs. +NO_OP = object() diff --git a/axios-example/lib/python3.10/site-packages/attr/setters.pyi b/axios-example/lib/python3.10/site-packages/attr/setters.pyi new file mode 100644 index 0000000..3f5603c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/setters.pyi @@ -0,0 +1,19 @@ +from typing import Any, NewType, NoReturn, TypeVar, cast + +from . import Attribute, _OnSetAttrType + +_T = TypeVar("_T") + +def frozen( + instance: Any, attribute: Attribute[Any], new_value: Any +) -> NoReturn: ... +def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ... +def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ... + +# convert is allowed to return Any, because they can be chained using pipe. +def convert( + instance: Any, attribute: Attribute[Any], new_value: Any +) -> Any: ... + +_NoOpType = NewType("_NoOpType", object) +NO_OP: _NoOpType diff --git a/axios-example/lib/python3.10/site-packages/attr/validators.py b/axios-example/lib/python3.10/site-packages/attr/validators.py new file mode 100644 index 0000000..eece517 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/validators.py @@ -0,0 +1,594 @@ +# SPDX-License-Identifier: MIT + +""" +Commonly useful validators. +""" + + +import operator +import re + +from contextlib import contextmanager + +from ._config import get_run_validators, set_run_validators +from ._make import _AndValidator, and_, attrib, attrs +from .exceptions import NotCallableError + + +try: + Pattern = re.Pattern +except AttributeError: # Python <3.7 lacks a Pattern type. + Pattern = type(re.compile("")) + + +__all__ = [ + "and_", + "deep_iterable", + "deep_mapping", + "disabled", + "ge", + "get_disabled", + "gt", + "in_", + "instance_of", + "is_callable", + "le", + "lt", + "matches_re", + "max_len", + "min_len", + "optional", + "provides", + "set_disabled", +] + + +def set_disabled(disabled): + """ + Globally disable or enable running validators. + + By default, they are run. + + :param disabled: If ``True``, disable running all validators. + :type disabled: bool + + .. warning:: + + This function is not thread-safe! + + .. versionadded:: 21.3.0 + """ + set_run_validators(not disabled) + + +def get_disabled(): + """ + Return a bool indicating whether validators are currently disabled or not. + + :return: ``True`` if validators are currently disabled. + :rtype: bool + + .. versionadded:: 21.3.0 + """ + return not get_run_validators() + + +@contextmanager +def disabled(): + """ + Context manager that disables running validators within its context. + + .. warning:: + + This context manager is not thread-safe! + + .. versionadded:: 21.3.0 + """ + set_run_validators(False) + try: + yield + finally: + set_run_validators(True) + + +@attrs(repr=False, slots=True, hash=True) +class _InstanceOfValidator: + type = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not isinstance(value, self.type): + raise TypeError( + "'{name}' must be {type!r} (got {value!r} that is a " + "{actual!r}).".format( + name=attr.name, + type=self.type, + actual=value.__class__, + value=value, + ), + attr, + self.type, + value, + ) + + def __repr__(self): + return "".format( + type=self.type + ) + + +def instance_of(type): + """ + A validator that raises a `TypeError` if the initializer is called + with a wrong type for this particular attribute (checks are performed using + `isinstance` therefore it's also valid to pass a tuple of types). + + :param type: The type to check for. + :type type: type or tuple of types + + :raises TypeError: With a human readable error message, the attribute + (of type `attrs.Attribute`), the expected type, and the value it + got. + """ + return _InstanceOfValidator(type) + + +@attrs(repr=False, frozen=True, slots=True) +class _MatchesReValidator: + pattern = attrib() + match_func = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.match_func(value): + raise ValueError( + "'{name}' must match regex {pattern!r}" + " ({value!r} doesn't)".format( + name=attr.name, pattern=self.pattern.pattern, value=value + ), + attr, + self.pattern, + value, + ) + + def __repr__(self): + return "".format( + pattern=self.pattern + ) + + +def matches_re(regex, flags=0, func=None): + r""" + A validator that raises `ValueError` if the initializer is called + with a string that doesn't match *regex*. + + :param regex: a regex string or precompiled pattern to match against + :param int flags: flags that will be passed to the underlying re function + (default 0) + :param callable func: which underlying `re` function to call. Valid options + are `re.fullmatch`, `re.search`, and `re.match`; the default ``None`` + means `re.fullmatch`. For performance reasons, the pattern is always + precompiled using `re.compile`. + + .. versionadded:: 19.2.0 + .. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern. + """ + valid_funcs = (re.fullmatch, None, re.search, re.match) + if func not in valid_funcs: + raise ValueError( + "'func' must be one of {}.".format( + ", ".join( + sorted( + e and e.__name__ or "None" for e in set(valid_funcs) + ) + ) + ) + ) + + if isinstance(regex, Pattern): + if flags: + raise TypeError( + "'flags' can only be used with a string pattern; " + "pass flags to re.compile() instead" + ) + pattern = regex + else: + pattern = re.compile(regex, flags) + + if func is re.match: + match_func = pattern.match + elif func is re.search: + match_func = pattern.search + else: + match_func = pattern.fullmatch + + return _MatchesReValidator(pattern, match_func) + + +@attrs(repr=False, slots=True, hash=True) +class _ProvidesValidator: + interface = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.interface.providedBy(value): + raise TypeError( + "'{name}' must provide {interface!r} which {value!r} " + "doesn't.".format( + name=attr.name, interface=self.interface, value=value + ), + attr, + self.interface, + value, + ) + + def __repr__(self): + return "".format( + interface=self.interface + ) + + +def provides(interface): + """ + A validator that raises a `TypeError` if the initializer is called + with an object that does not provide the requested *interface* (checks are + performed using ``interface.providedBy(value)`` (see `zope.interface + `_). + + :param interface: The interface to check for. + :type interface: ``zope.interface.Interface`` + + :raises TypeError: With a human readable error message, the attribute + (of type `attrs.Attribute`), the expected interface, and the + value it got. + """ + return _ProvidesValidator(interface) + + +@attrs(repr=False, slots=True, hash=True) +class _OptionalValidator: + validator = attrib() + + def __call__(self, inst, attr, value): + if value is None: + return + + self.validator(inst, attr, value) + + def __repr__(self): + return "".format( + what=repr(self.validator) + ) + + +def optional(validator): + """ + A validator that makes an attribute optional. An optional attribute is one + which can be set to ``None`` in addition to satisfying the requirements of + the sub-validator. + + :param validator: A validator (or a list of validators) that is used for + non-``None`` values. + :type validator: callable or `list` of callables. + + .. versionadded:: 15.1.0 + .. versionchanged:: 17.1.0 *validator* can be a list of validators. + """ + if isinstance(validator, list): + return _OptionalValidator(_AndValidator(validator)) + return _OptionalValidator(validator) + + +@attrs(repr=False, slots=True, hash=True) +class _InValidator: + options = attrib() + + def __call__(self, inst, attr, value): + try: + in_options = value in self.options + except TypeError: # e.g. `1 in "abc"` + in_options = False + + if not in_options: + raise ValueError( + "'{name}' must be in {options!r} (got {value!r})".format( + name=attr.name, options=self.options, value=value + ), + attr, + self.options, + value, + ) + + def __repr__(self): + return "".format( + options=self.options + ) + + +def in_(options): + """ + A validator that raises a `ValueError` if the initializer is called + with a value that does not belong in the options provided. The check is + performed using ``value in options``. + + :param options: Allowed options. + :type options: list, tuple, `enum.Enum`, ... + + :raises ValueError: With a human readable error message, the attribute (of + type `attrs.Attribute`), the expected options, and the value it + got. + + .. versionadded:: 17.1.0 + .. versionchanged:: 22.1.0 + The ValueError was incomplete until now and only contained the human + readable error message. Now it contains all the information that has + been promised since 17.1.0. + """ + return _InValidator(options) + + +@attrs(repr=False, slots=False, hash=True) +class _IsCallableValidator: + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not callable(value): + message = ( + "'{name}' must be callable " + "(got {value!r} that is a {actual!r})." + ) + raise NotCallableError( + msg=message.format( + name=attr.name, value=value, actual=value.__class__ + ), + value=value, + ) + + def __repr__(self): + return "" + + +def is_callable(): + """ + A validator that raises a `attr.exceptions.NotCallableError` if the + initializer is called with a value for this particular attribute + that is not callable. + + .. versionadded:: 19.1.0 + + :raises `attr.exceptions.NotCallableError`: With a human readable error + message containing the attribute (`attrs.Attribute`) name, + and the value it got. + """ + return _IsCallableValidator() + + +@attrs(repr=False, slots=True, hash=True) +class _DeepIterable: + member_validator = attrib(validator=is_callable()) + iterable_validator = attrib( + default=None, validator=optional(is_callable()) + ) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.iterable_validator is not None: + self.iterable_validator(inst, attr, value) + + for member in value: + self.member_validator(inst, attr, member) + + def __repr__(self): + iterable_identifier = ( + "" + if self.iterable_validator is None + else " {iterable!r}".format(iterable=self.iterable_validator) + ) + return ( + "" + ).format( + iterable_identifier=iterable_identifier, + member=self.member_validator, + ) + + +def deep_iterable(member_validator, iterable_validator=None): + """ + A validator that performs deep validation of an iterable. + + :param member_validator: Validator(s) to apply to iterable members + :param iterable_validator: Validator to apply to iterable itself + (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + if isinstance(member_validator, (list, tuple)): + member_validator = and_(*member_validator) + return _DeepIterable(member_validator, iterable_validator) + + +@attrs(repr=False, slots=True, hash=True) +class _DeepMapping: + key_validator = attrib(validator=is_callable()) + value_validator = attrib(validator=is_callable()) + mapping_validator = attrib(default=None, validator=optional(is_callable())) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.mapping_validator is not None: + self.mapping_validator(inst, attr, value) + + for key in value: + self.key_validator(inst, attr, key) + self.value_validator(inst, attr, value[key]) + + def __repr__(self): + return ( + "" + ).format(key=self.key_validator, value=self.value_validator) + + +def deep_mapping(key_validator, value_validator, mapping_validator=None): + """ + A validator that performs deep validation of a dictionary. + + :param key_validator: Validator to apply to dictionary keys + :param value_validator: Validator to apply to dictionary values + :param mapping_validator: Validator to apply to top-level mapping + attribute (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + return _DeepMapping(key_validator, value_validator, mapping_validator) + + +@attrs(repr=False, frozen=True, slots=True) +class _NumberValidator: + bound = attrib() + compare_op = attrib() + compare_func = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.compare_func(value, self.bound): + raise ValueError( + "'{name}' must be {op} {bound}: {value}".format( + name=attr.name, + op=self.compare_op, + bound=self.bound, + value=value, + ) + ) + + def __repr__(self): + return "".format( + op=self.compare_op, bound=self.bound + ) + + +def lt(val): + """ + A validator that raises `ValueError` if the initializer is called + with a number larger or equal to *val*. + + :param val: Exclusive upper bound for values + + .. versionadded:: 21.3.0 + """ + return _NumberValidator(val, "<", operator.lt) + + +def le(val): + """ + A validator that raises `ValueError` if the initializer is called + with a number greater than *val*. + + :param val: Inclusive upper bound for values + + .. versionadded:: 21.3.0 + """ + return _NumberValidator(val, "<=", operator.le) + + +def ge(val): + """ + A validator that raises `ValueError` if the initializer is called + with a number smaller than *val*. + + :param val: Inclusive lower bound for values + + .. versionadded:: 21.3.0 + """ + return _NumberValidator(val, ">=", operator.ge) + + +def gt(val): + """ + A validator that raises `ValueError` if the initializer is called + with a number smaller or equal to *val*. + + :param val: Exclusive lower bound for values + + .. versionadded:: 21.3.0 + """ + return _NumberValidator(val, ">", operator.gt) + + +@attrs(repr=False, frozen=True, slots=True) +class _MaxLengthValidator: + max_length = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if len(value) > self.max_length: + raise ValueError( + "Length of '{name}' must be <= {max}: {len}".format( + name=attr.name, max=self.max_length, len=len(value) + ) + ) + + def __repr__(self): + return "".format(max=self.max_length) + + +def max_len(length): + """ + A validator that raises `ValueError` if the initializer is called + with a string or iterable that is longer than *length*. + + :param int length: Maximum length of the string or iterable + + .. versionadded:: 21.3.0 + """ + return _MaxLengthValidator(length) + + +@attrs(repr=False, frozen=True, slots=True) +class _MinLengthValidator: + min_length = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if len(value) < self.min_length: + raise ValueError( + "Length of '{name}' must be => {min}: {len}".format( + name=attr.name, min=self.min_length, len=len(value) + ) + ) + + def __repr__(self): + return "".format(min=self.min_length) + + +def min_len(length): + """ + A validator that raises `ValueError` if the initializer is called + with a string or iterable that is shorter than *length*. + + :param int length: Minimum length of the string or iterable + + .. versionadded:: 22.1.0 + """ + return _MinLengthValidator(length) diff --git a/axios-example/lib/python3.10/site-packages/attr/validators.pyi b/axios-example/lib/python3.10/site-packages/attr/validators.pyi new file mode 100644 index 0000000..54b9dba --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attr/validators.pyi @@ -0,0 +1,80 @@ +from typing import ( + Any, + AnyStr, + Callable, + Container, + ContextManager, + Iterable, + List, + Mapping, + Match, + Optional, + Pattern, + Tuple, + Type, + TypeVar, + Union, + overload, +) + +from . import _ValidatorType +from . import _ValidatorArgType + +_T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") +_T3 = TypeVar("_T3") +_I = TypeVar("_I", bound=Iterable) +_K = TypeVar("_K") +_V = TypeVar("_V") +_M = TypeVar("_M", bound=Mapping) + +def set_disabled(run: bool) -> None: ... +def get_disabled() -> bool: ... +def disabled() -> ContextManager[None]: ... + +# To be more precise on instance_of use some overloads. +# If there are more than 3 items in the tuple then we fall back to Any +@overload +def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... +@overload +def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ... +@overload +def instance_of( + type: Tuple[Type[_T1], Type[_T2]] +) -> _ValidatorType[Union[_T1, _T2]]: ... +@overload +def instance_of( + type: Tuple[Type[_T1], Type[_T2], Type[_T3]] +) -> _ValidatorType[Union[_T1, _T2, _T3]]: ... +@overload +def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ... +def provides(interface: Any) -> _ValidatorType[Any]: ... +def optional( + validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]] +) -> _ValidatorType[Optional[_T]]: ... +def in_(options: Container[_T]) -> _ValidatorType[_T]: ... +def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... +def matches_re( + regex: Union[Pattern[AnyStr], AnyStr], + flags: int = ..., + func: Optional[ + Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]] + ] = ..., +) -> _ValidatorType[AnyStr]: ... +def deep_iterable( + member_validator: _ValidatorArgType[_T], + iterable_validator: Optional[_ValidatorType[_I]] = ..., +) -> _ValidatorType[_I]: ... +def deep_mapping( + key_validator: _ValidatorType[_K], + value_validator: _ValidatorType[_V], + mapping_validator: Optional[_ValidatorType[_M]] = ..., +) -> _ValidatorType[_M]: ... +def is_callable() -> _ValidatorType[_T]: ... +def lt(val: _T) -> _ValidatorType[_T]: ... +def le(val: _T) -> _ValidatorType[_T]: ... +def ge(val: _T) -> _ValidatorType[_T]: ... +def gt(val: _T) -> _ValidatorType[_T]: ... +def max_len(length: int) -> _ValidatorType[_T]: ... +def min_len(length: int) -> _ValidatorType[_T]: ... diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/AUTHORS.rst b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/AUTHORS.rst new file mode 100644 index 0000000..aa677e8 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/AUTHORS.rst @@ -0,0 +1,11 @@ +Credits +======= + +``attrs`` is written and maintained by `Hynek Schlawack `_. + +The development is kindly supported by `Variomedia AG `_. + +A full list of contributors can be found in `GitHub's overview `_. + +It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions. +Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay? diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/LICENSE new file mode 100644 index 0000000..2bd6453 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Hynek Schlawack and the attrs contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/METADATA new file mode 100644 index 0000000..60b6653 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/METADATA @@ -0,0 +1,240 @@ +Metadata-Version: 2.1 +Name: attrs +Version: 22.1.0 +Summary: Classes Without Boilerplate +Home-page: https://www.attrs.org/ +Author: Hynek Schlawack +Author-email: hs@ox.cx +Maintainer: Hynek Schlawack +Maintainer-email: hs@ox.cx +License: MIT +Project-URL: Documentation, https://www.attrs.org/ +Project-URL: Changelog, https://www.attrs.org/en/stable/changelog.html +Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues +Project-URL: Source Code, https://github.com/python-attrs/attrs +Project-URL: Funding, https://github.com/sponsors/hynek +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi +Project-URL: Ko-fi, https://ko-fi.com/the_hynek +Keywords: class,attribute,boilerplate +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Natural Language :: English +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: >=3.5 +Description-Content-Type: text/x-rst +License-File: LICENSE +License-File: AUTHORS.rst +Provides-Extra: dev +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'dev' +Requires-Dist: hypothesis ; extra == 'dev' +Requires-Dist: pympler ; extra == 'dev' +Requires-Dist: pytest (>=4.3.0) ; extra == 'dev' +Requires-Dist: mypy (!=0.940,>=0.900) ; extra == 'dev' +Requires-Dist: pytest-mypy-plugins ; extra == 'dev' +Requires-Dist: zope.interface ; extra == 'dev' +Requires-Dist: furo ; extra == 'dev' +Requires-Dist: sphinx ; extra == 'dev' +Requires-Dist: sphinx-notfound-page ; extra == 'dev' +Requires-Dist: pre-commit ; extra == 'dev' +Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'dev' +Provides-Extra: docs +Requires-Dist: furo ; extra == 'docs' +Requires-Dist: sphinx ; extra == 'docs' +Requires-Dist: zope.interface ; extra == 'docs' +Requires-Dist: sphinx-notfound-page ; extra == 'docs' +Provides-Extra: tests +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests' +Requires-Dist: hypothesis ; extra == 'tests' +Requires-Dist: pympler ; extra == 'tests' +Requires-Dist: pytest (>=4.3.0) ; extra == 'tests' +Requires-Dist: mypy (!=0.940,>=0.900) ; extra == 'tests' +Requires-Dist: pytest-mypy-plugins ; extra == 'tests' +Requires-Dist: zope.interface ; extra == 'tests' +Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'tests' +Provides-Extra: tests_no_zope +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope' +Requires-Dist: hypothesis ; extra == 'tests_no_zope' +Requires-Dist: pympler ; extra == 'tests_no_zope' +Requires-Dist: pytest (>=4.3.0) ; extra == 'tests_no_zope' +Requires-Dist: mypy (!=0.940,>=0.900) ; extra == 'tests_no_zope' +Requires-Dist: pytest-mypy-plugins ; extra == 'tests_no_zope' +Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'tests_no_zope' + + +.. image:: https://www.attrs.org/en/stable/_static/attrs_logo.png + :alt: attrs logo + :align: center + + +``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder methods `_). +`Trusted by NASA `_ for Mars missions since 2020! + +Its main goal is to help you to write **concise** and **correct** software without slowing down your code. + +.. teaser-end + +For that, it gives you a class decorator and a way to declaratively define the attributes on that class: + +.. -code-begin- + +.. code-block:: pycon + + >>> from attrs import asdict, define, make_class, Factory + + >>> @define + ... class SomeClass: + ... a_number: int = 42 + ... list_of_numbers: list[int] = Factory(list) + ... + ... def hard_math(self, another_number): + ... return self.a_number + sum(self.list_of_numbers) * another_number + + + >>> sc = SomeClass(1, [1, 2, 3]) + >>> sc + SomeClass(a_number=1, list_of_numbers=[1, 2, 3]) + + >>> sc.hard_math(3) + 19 + >>> sc == SomeClass(1, [1, 2, 3]) + True + >>> sc != SomeClass(2, [3, 2, 1]) + True + + >>> asdict(sc) + {'a_number': 1, 'list_of_numbers': [1, 2, 3]} + + >>> SomeClass() + SomeClass(a_number=42, list_of_numbers=[]) + + >>> C = make_class("C", ["a", "b"]) + >>> C("foo", "bar") + C(a='foo', b='bar') + + +After *declaring* your attributes, ``attrs`` gives you: + +- a concise and explicit overview of the class's attributes, +- a nice human-readable ``__repr__``, +- equality-checking methods, +- an initializer, +- and much more, + +*without* writing dull boilerplate code again and again and *without* runtime performance penalties. + +**Hate type annotations**!? +No problem! +Types are entirely **optional** with ``attrs``. +Simply assign ``attrs.field()`` to the attributes instead of annotating them with types. + +---- + +This example uses ``attrs``'s modern APIs that have been introduced in version 20.1.0, and the ``attrs`` package import name that has been added in version 21.3.0. +The classic APIs (``@attr.s``, ``attr.ib``, plus their serious-business aliases) and the ``attr`` package import name will remain **indefinitely**. + +Please check out `On The Core API Names `_ for a more in-depth explanation. + + +Data Classes +============ + +On the tin, ``attrs`` might remind you of ``dataclasses`` (and indeed, ``dataclasses`` `are a descendant `_ of ``attrs``). +In practice it does a lot more and is more flexible. +For instance it allows you to define `special handling of NumPy arrays for equality checks `_, or allows more ways to `plug into the initialization process `_. + +For more details, please refer to our `comparison page `_. + +.. -project-information- + +Project Information +=================== + +- **License**: `MIT `_ +- **PyPI**: https://pypi.org/project/attrs/ +- **Source Code**: https://github.com/python-attrs/attrs +- **Documentation**: https://www.attrs.org/ +- **Changelog**: https://www.attrs.org/en/stable/changelog.html +- **Get Help**: please use the ``python-attrs`` tag on `StackOverflow `_ +- **Third-party Extensions**: https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs +- **Supported Python Versions**: 3.5 and later (last 2.7-compatible release is `21.4.0 `_) + +If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started! + + +``attrs`` for Enterprise +------------------------ + +Available as part of the Tidelift Subscription. + +The maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. +Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. +`Learn more. `_ + + +Release Information +=================== + +22.1.0 (2022-07-28) +------------------- + +Backwards-incompatible Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Python 2.7 is not supported anymore. + + Dealing with Python 2.7 tooling has become too difficult for a volunteer-run project. + + We have supported Python 2 more than 2 years after it was officially discontinued and feel that we have paid our dues. + All version up to 21.4.0 from December 2021 remain fully functional, of course. + `#936 `_ +- The deprecated ``cmp`` attribute of ``attrs.Attribute`` has been removed. + This does not affect the *cmp* argument to ``attr.s`` that can be used as a shortcut to set *eq* and *order* at the same time. + `#939 `_ + + +Changes +^^^^^^^ + +- Instantiation of frozen slotted classes is now faster. + `#898 `_ +- If an ``eq`` key is defined, it is also used before hashing the attribute. + `#909 `_ +- Added ``attrs.validators.min_len()``. + `#916 `_ +- ``attrs.validators.deep_iterable()``'s *member_validator* argument now also accepts a list of validators and wraps them in an ``attrs.validators.and_()``. + `#925 `_ +- Added missing type stub re-imports for ``attrs.converters`` and ``attrs.filters``. + `#931 `_ +- Added missing stub for ``attr(s).cmp_using()``. + `#949 `_ +- ``attrs.validators._in()``'s ``ValueError`` is not missing the attribute, expected options, and the value it got anymore. + `#951 `_ +- Python 3.11 is now officially supported. + `#969 `_ + +`Full changelog `_. + +Credits +======= + +``attrs`` is written and maintained by `Hynek Schlawack `_. + +The development is kindly supported by `Variomedia AG `_. + +A full list of contributors can be found in `GitHub's overview `_. + +It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions. +Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay? diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/RECORD new file mode 100644 index 0000000..7288f98 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/RECORD @@ -0,0 +1,56 @@ +attr/__init__.py,sha256=KZjj88xCd_tH-W59HR1EvHiYAUi4Zd1dzOxx8P77jeI,1602 +attr/__init__.pyi,sha256=t-1r-I1VnyxFrqic__QxIk1HUc3ag53L2b8lv0xDZTw,15137 +attr/__pycache__/__init__.cpython-310.pyc,, +attr/__pycache__/_cmp.cpython-310.pyc,, +attr/__pycache__/_compat.cpython-310.pyc,, +attr/__pycache__/_config.cpython-310.pyc,, +attr/__pycache__/_funcs.cpython-310.pyc,, +attr/__pycache__/_make.cpython-310.pyc,, +attr/__pycache__/_next_gen.cpython-310.pyc,, +attr/__pycache__/_version_info.cpython-310.pyc,, +attr/__pycache__/converters.cpython-310.pyc,, +attr/__pycache__/exceptions.cpython-310.pyc,, +attr/__pycache__/filters.cpython-310.pyc,, +attr/__pycache__/setters.cpython-310.pyc,, +attr/__pycache__/validators.cpython-310.pyc,, +attr/_cmp.py,sha256=Mmqj-6w71g_vx0TTLLkU4pbmv28qz_FyBGcUb1HX9ZE,4102 +attr/_cmp.pyi,sha256=cSlVvIH4As2NlDIoLglPEbSrBMWVVTpwExVDDBH6pn8,357 +attr/_compat.py,sha256=Qr9kZOu95Og7joPaQiXoPb54epKqxNU39Xu0u4QVGZI,5568 +attr/_config.py,sha256=5W8lgRePuIOWu1ZuqF1899e2CmXGc95-ipwTpF1cEU4,826 +attr/_funcs.py,sha256=XTFKZtd5zxsUvWocBw7VAswTxH-nFHk0H8gJ2JQkxD4,14645 +attr/_make.py,sha256=Srxbhb8kB17T6nP9e_dgcXY72zda9xfL5uJzva6LExY,97569 +attr/_next_gen.py,sha256=N0Gb5WdBHfcfQhcUsLAc_2ZYzl0JtAX1NOHuDgvkecE,5882 +attr/_version_info.py,sha256=exSqb3b5E-fMSsgZAlEw9XcLpEgobPORCZpcaEglAM4,2121 +attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209 +attr/converters.py,sha256=TWCfmCAxk8s2tgTSYnyQv9MRDPf1pk8Rj16KO_Xqe1c,3610 +attr/converters.pyi,sha256=MQo7iEzPNVoFpKqD30sVwgVpdNoIeSCF2nsXvoxLZ-Y,416 +attr/exceptions.py,sha256=ZGEMLv0CDY1TOtj49OF84myejOn-LCCXAKGIKalKkVU,1915 +attr/exceptions.pyi,sha256=zZq8bCUnKAy9mDtBEw42ZhPhAUIHoTKedDQInJD883M,539 +attr/filters.py,sha256=aZep54h8-4ZYV5lmZ3Dx2mqeQH4cMx6tuCmCylLNbEU,1038 +attr/filters.pyi,sha256=_Sm80jGySETX_Clzdkon5NHVjQWRl3Y3liQKZX1czXc,215 +attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +attr/setters.py,sha256=pbCZQ-pE6ZxjDqZfWWUhUFefXtpekIU4qS_YDMLPQ50,1400 +attr/setters.pyi,sha256=7dM10rqpQVDW0y-iJUnq8rabdO5Wx2Sbo5LwNa0IXl0,573 +attr/validators.py,sha256=cpOHMNSt02ApbTQtQAwBTMeWZqp0u_sx-e3xH-jTyR4,16793 +attr/validators.pyi,sha256=6ngbvnWnFSkbf5J2dK86pq2xpEtrwzWTKfJ4aUvSIlk,2355 +attrs-22.1.0.dist-info/AUTHORS.rst,sha256=jau5p7JMPbBJeCCpGBWsRj8zpxUVAhpyoHFJRfjM888,743 +attrs-22.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +attrs-22.1.0.dist-info/LICENSE,sha256=iCEVyV38KvHutnFPjsbVy8q_Znyv-HKfQkINpj9xTp8,1109 +attrs-22.1.0.dist-info/METADATA,sha256=vwSMK_BbEgVHrgFWpj3iW0PISTMPHzi6qham9jg7LtA,11015 +attrs-22.1.0.dist-info/RECORD,, +attrs-22.1.0.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110 +attrs-22.1.0.dist-info/top_level.txt,sha256=AGbmKnOtYpdkLRsDRQVSBIwfL32pAQ6BSo1mt-BxI7M,11 +attrs/__init__.py,sha256=CeyxLGVViAEKKsLOLaif8vF3vs1a28vsrRVLv7eMEgM,1109 +attrs/__init__.pyi,sha256=vuFxNbulP9Q7hfpO6Lb5A-_0mbEJOiwYyefjzXMqVfs,2100 +attrs/__pycache__/__init__.cpython-310.pyc,, +attrs/__pycache__/converters.cpython-310.pyc,, +attrs/__pycache__/exceptions.cpython-310.pyc,, +attrs/__pycache__/filters.cpython-310.pyc,, +attrs/__pycache__/setters.cpython-310.pyc,, +attrs/__pycache__/validators.cpython-310.pyc,, +attrs/converters.py,sha256=fCBEdlYWcmI3sCnpUk2pz22GYtXzqTkp6NeOpdI64PY,70 +attrs/exceptions.py,sha256=SlDli6AY77f6ny-H7oy98OkQjsrw-D_supEuErIVYkE,70 +attrs/filters.py,sha256=dc_dNey29kH6KLU1mT2Dakq7tZ3kBfzEGwzOmDzw1F8,67 +attrs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +attrs/setters.py,sha256=oKw51C72Hh45wTwYvDHJP9kbicxiMhMR4Y5GvdpKdHQ,67 +attrs/validators.py,sha256=4ag1SyVD2Hm3PYKiNG_NOtR_e7f81Hr6GiNl4YvXo4Q,70 diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/WHEEL new file mode 100644 index 0000000..0b18a28 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/top_level.txt new file mode 100644 index 0000000..eca8ba9 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs-22.1.0.dist-info/top_level.txt @@ -0,0 +1,2 @@ +attr +attrs diff --git a/axios-example/lib/python3.10/site-packages/attrs/__init__.py b/axios-example/lib/python3.10/site-packages/attrs/__init__.py new file mode 100644 index 0000000..a704b8b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/__init__.py @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: MIT + +from attr import ( + NOTHING, + Attribute, + Factory, + __author__, + __copyright__, + __description__, + __doc__, + __email__, + __license__, + __title__, + __url__, + __version__, + __version_info__, + assoc, + cmp_using, + define, + evolve, + field, + fields, + fields_dict, + frozen, + has, + make_class, + mutable, + resolve_types, + validate, +) +from attr._next_gen import asdict, astuple + +from . import converters, exceptions, filters, setters, validators + + +__all__ = [ + "__author__", + "__copyright__", + "__description__", + "__doc__", + "__email__", + "__license__", + "__title__", + "__url__", + "__version__", + "__version_info__", + "asdict", + "assoc", + "astuple", + "Attribute", + "cmp_using", + "converters", + "define", + "evolve", + "exceptions", + "Factory", + "field", + "fields_dict", + "fields", + "filters", + "frozen", + "has", + "make_class", + "mutable", + "NOTHING", + "resolve_types", + "setters", + "validate", + "validators", +] diff --git a/axios-example/lib/python3.10/site-packages/attrs/__init__.pyi b/axios-example/lib/python3.10/site-packages/attrs/__init__.pyi new file mode 100644 index 0000000..fc44de4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/__init__.pyi @@ -0,0 +1,66 @@ +from typing import ( + Any, + Callable, + Dict, + Mapping, + Optional, + Sequence, + Tuple, + Type, +) + +# Because we need to type our own stuff, we have to make everything from +# attr explicitly public too. +from attr import __author__ as __author__ +from attr import __copyright__ as __copyright__ +from attr import __description__ as __description__ +from attr import __email__ as __email__ +from attr import __license__ as __license__ +from attr import __title__ as __title__ +from attr import __url__ as __url__ +from attr import __version__ as __version__ +from attr import __version_info__ as __version_info__ +from attr import _FilterType +from attr import assoc as assoc +from attr import Attribute as Attribute +from attr import cmp_using as cmp_using +from attr import converters as converters +from attr import define as define +from attr import evolve as evolve +from attr import exceptions as exceptions +from attr import Factory as Factory +from attr import field as field +from attr import fields as fields +from attr import fields_dict as fields_dict +from attr import filters as filters +from attr import frozen as frozen +from attr import has as has +from attr import make_class as make_class +from attr import mutable as mutable +from attr import NOTHING as NOTHING +from attr import resolve_types as resolve_types +from attr import setters as setters +from attr import validate as validate +from attr import validators as validators + +# TODO: see definition of attr.asdict/astuple +def asdict( + inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + dict_factory: Type[Mapping[Any, Any]] = ..., + retain_collection_types: bool = ..., + value_serializer: Optional[ + Callable[[type, Attribute[Any], Any], Any] + ] = ..., + tuple_keys: bool = ..., +) -> Dict[str, Any]: ... + +# TODO: add support for returning NamedTuple from the mypy plugin +def astuple( + inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + tuple_factory: Type[Sequence[Any]] = ..., + retain_collection_types: bool = ..., +) -> Tuple[Any, ...]: ... diff --git a/axios-example/lib/python3.10/site-packages/attrs/converters.py b/axios-example/lib/python3.10/site-packages/attrs/converters.py new file mode 100644 index 0000000..edfa8d3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/converters.py @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT + +from attr.converters import * # noqa diff --git a/axios-example/lib/python3.10/site-packages/attrs/exceptions.py b/axios-example/lib/python3.10/site-packages/attrs/exceptions.py new file mode 100644 index 0000000..bd9efed --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/exceptions.py @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT + +from attr.exceptions import * # noqa diff --git a/axios-example/lib/python3.10/site-packages/attrs/filters.py b/axios-example/lib/python3.10/site-packages/attrs/filters.py new file mode 100644 index 0000000..5295900 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/filters.py @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT + +from attr.filters import * # noqa diff --git a/axios-example/lib/python3.10/site-packages/attrs/py.typed b/axios-example/lib/python3.10/site-packages/attrs/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/attrs/setters.py b/axios-example/lib/python3.10/site-packages/attrs/setters.py new file mode 100644 index 0000000..9b50770 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/setters.py @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT + +from attr.setters import * # noqa diff --git a/axios-example/lib/python3.10/site-packages/attrs/validators.py b/axios-example/lib/python3.10/site-packages/attrs/validators.py new file mode 100644 index 0000000..ab2c9b3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/attrs/validators.py @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT + +from attr.validators import * # noqa diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/LICENSE new file mode 100644 index 0000000..0a64774 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/LICENSE @@ -0,0 +1,21 @@ +This package contains a modified version of ca-bundle.crt: + +ca-bundle.crt -- Bundle of CA Root Certificates + +Certificate data from Mozilla as of: Thu Nov 3 19:04:19 2011# +This is a bundle of X.509 certificates of public Certificate Authorities +(CA). These were automatically extracted from Mozilla's root certificates +file (certdata.txt). This file can be found in the mozilla source tree: +https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt +It contains the certificates in PEM format and therefore +can be directly used with curl / libcurl / php_curl, or with +an Apache+mod_ssl webserver for SSL client authentication. +Just configure this file as the SSLCACertificateFile.# + +***** BEGIN LICENSE BLOCK ***** +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +***** END LICENSE BLOCK ***** +@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/METADATA new file mode 100644 index 0000000..aeb1991 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/METADATA @@ -0,0 +1,83 @@ +Metadata-Version: 2.1 +Name: certifi +Version: 2022.12.7 +Summary: Python package for providing Mozilla's CA Bundle. +Home-page: https://github.com/certifi/python-certifi +Author: Kenneth Reitz +Author-email: me@kennethreitz.com +License: MPL-2.0 +Project-URL: Source, https://github.com/certifi/python-certifi +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) +Classifier: Natural Language :: English +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Requires-Python: >=3.6 +License-File: LICENSE + +Certifi: Python SSL Certificates +================================ + +Certifi provides Mozilla's carefully curated collection of Root Certificates for +validating the trustworthiness of SSL certificates while verifying the identity +of TLS hosts. It has been extracted from the `Requests`_ project. + +Installation +------------ + +``certifi`` is available on PyPI. Simply install it with ``pip``:: + + $ pip install certifi + +Usage +----- + +To reference the installed certificate authority (CA) bundle, you can use the +built-in function:: + + >>> import certifi + + >>> certifi.where() + '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' + +Or from the command line:: + + $ python -m certifi + /usr/local/lib/python3.7/site-packages/certifi/cacert.pem + +Enjoy! + +1024-bit Root Certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Browsers and certificate authorities have concluded that 1024-bit keys are +unacceptably weak for certificates, particularly root certificates. For this +reason, Mozilla has removed any weak (i.e. 1024-bit key) certificate from its +bundle, replacing it with an equivalent strong (i.e. 2048-bit or greater key) +certificate from the same CA. Because Mozilla removed these certificates from +its bundle, ``certifi`` removed them as well. + +In previous versions, ``certifi`` provided the ``certifi.old_where()`` function +to intentionally re-add the 1024-bit roots back into your bundle. This was not +recommended in production and therefore was removed at the end of 2018. + +.. _`Requests`: https://requests.readthedocs.io/en/master/ + +Addition/Removal of Certificates +-------------------------------- + +Certifi does not support any addition/removal or other modification of the +CA trust store content. This project is intended to provide a reliable and +highly portable root of trust to python deployments. Look to upstream projects +for methods to use alternate trust. + + diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/RECORD new file mode 100644 index 0000000..16de1d3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/RECORD @@ -0,0 +1,14 @@ +certifi-2022.12.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +certifi-2022.12.7.dist-info/LICENSE,sha256=oC9sY4-fuE0G93ZMOrCF2K9-2luTwWbaVDEkeQd8b7A,1052 +certifi-2022.12.7.dist-info/METADATA,sha256=chFpcxKhCPEQ3d8-Vz36zr2Micf1eQhKkFFk7_JvJNo,2911 +certifi-2022.12.7.dist-info/RECORD,, +certifi-2022.12.7.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92 +certifi-2022.12.7.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi/__init__.py,sha256=bK_nm9bLJzNvWZc2oZdiTwg2KWD4HSPBWGaM0zUDvMw,94 +certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 +certifi/__pycache__/__init__.cpython-310.pyc,, +certifi/__pycache__/__main__.cpython-310.pyc,, +certifi/__pycache__/core.cpython-310.pyc,, +certifi/cacert.pem,sha256=LBHDzgj_xA05AxnHK8ENT5COnGNElNZe0svFUHMf1SQ,275233 +certifi/core.py,sha256=lhewz0zFb2b4ULsQurElmloYwQoecjWzPqY67P8T7iM,4219 +certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/WHEEL new file mode 100644 index 0000000..5bad85f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/top_level.txt new file mode 100644 index 0000000..963eac5 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi-2022.12.7.dist-info/top_level.txt @@ -0,0 +1 @@ +certifi diff --git a/axios-example/lib/python3.10/site-packages/certifi/__init__.py b/axios-example/lib/python3.10/site-packages/certifi/__init__.py new file mode 100644 index 0000000..a3546f1 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi/__init__.py @@ -0,0 +1,4 @@ +from .core import contents, where + +__all__ = ["contents", "where"] +__version__ = "2022.12.07" diff --git a/axios-example/lib/python3.10/site-packages/certifi/__main__.py b/axios-example/lib/python3.10/site-packages/certifi/__main__.py new file mode 100644 index 0000000..8945b5d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi/__main__.py @@ -0,0 +1,12 @@ +import argparse + +from certifi import contents, where + +parser = argparse.ArgumentParser() +parser.add_argument("-c", "--contents", action="store_true") +args = parser.parse_args() + +if args.contents: + print(contents()) +else: + print(where()) diff --git a/axios-example/lib/python3.10/site-packages/certifi/cacert.pem b/axios-example/lib/python3.10/site-packages/certifi/cacert.pem new file mode 100644 index 0000000..df9e4e3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi/cacert.pem @@ -0,0 +1,4527 @@ + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Label: "TeliaSonera Root CA v1" +# Serial: 199041966741090107964904287217786801558 +# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c +# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 +# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Label: "E-Tugra Certification Authority" +# Serial: 7667447206703254355 +# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 +# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 +# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 2" +# Serial: 1 +# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a +# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 +# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot 2011 O=Atos +# Subject: CN=Atos TrustedRoot 2011 O=Atos +# Label: "Atos TrustedRoot 2011" +# Serial: 6643877497813316402 +# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 +# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 +# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 1 G3" +# Serial: 687049649626669250736271037606554624078720034195 +# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab +# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 +# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2 G3" +# Serial: 390156079458959257446133169266079962026824725800 +# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 +# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 +# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3 G3" +# Serial: 268090761170461462463995952157327242137089239581 +# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 +# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d +# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G2" +# Serial: 15385348160840213938643033620894905419 +# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d +# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f +# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G3" +# Serial: 15459312981008553731928384953135426796 +# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb +# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 +# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G2" +# Serial: 4293743540046975378534879503202253541 +# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 +# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 +# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G3" +# Serial: 7089244469030293291760083333884364146 +# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca +# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e +# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Trusted Root G4" +# Serial: 7451500558977370777930084869016614236 +# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 +# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 +# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Label: "COMODO RSA Certification Authority" +# Serial: 101909084537582093308941363524873193117 +# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 +# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 +# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Label: "USERTrust RSA Certification Authority" +# Serial: 2645093764781058787591871645665788717 +# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 +# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e +# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Label: "USERTrust ECC Certification Authority" +# Serial: 123013823720199481456569720443997572134 +# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 +# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 +# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Label: "GlobalSign ECC Root CA - R5" +# Serial: 32785792099990507226680698011560947931244 +# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 +# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa +# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Label: "IdenTrust Commercial Root CA 1" +# Serial: 13298821034946342390520003877796839426 +# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 +# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 +# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Label: "IdenTrust Public Sector Root CA 1" +# Serial: 13298821034946342390521976156843933698 +# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba +# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd +# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G2" +# Serial: 1246989352 +# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 +# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 +# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - EC1" +# Serial: 51543124481930649114116133369 +# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc +# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 +# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority +# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority +# Label: "CFCA EV ROOT" +# Serial: 407555286 +# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 +# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 +# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GB CA" +# Serial: 157768595616588414422159278966750757568 +# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d +# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed +# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Label: "SZAFIR ROOT CA2" +# Serial: 357043034767186914217277344587386743377558296292 +# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 +# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de +# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA 2" +# Serial: 44979900017204383099463764357512596969 +# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 +# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 +# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce +# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 +# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef +# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 +# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X1 O=Internet Security Research Group +# Subject: CN=ISRG Root X1 O=Internet Security Research Group +# Label: "ISRG Root X1" +# Serial: 172886928669790476064670243504169061120 +# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e +# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 +# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Label: "AC RAIZ FNMT-RCM" +# Serial: 485876308206448804701554682760554759 +# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d +# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 +# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 1 O=Amazon +# Subject: CN=Amazon Root CA 1 O=Amazon +# Label: "Amazon Root CA 1" +# Serial: 143266978916655856878034712317230054538369994 +# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 +# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 +# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 2 O=Amazon +# Subject: CN=Amazon Root CA 2 O=Amazon +# Label: "Amazon Root CA 2" +# Serial: 143266982885963551818349160658925006970653239 +# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 +# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a +# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 3 O=Amazon +# Subject: CN=Amazon Root CA 3 O=Amazon +# Label: "Amazon Root CA 3" +# Serial: 143266986699090766294700635381230934788665930 +# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 +# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e +# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 4 O=Amazon +# Subject: CN=Amazon Root CA 4 O=Amazon +# Label: "Amazon Root CA 4" +# Serial: 143266989758080763974105200630763877849284878 +# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd +# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be +# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# Serial: 1 +# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 +# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca +# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Label: "GDCA TrustAUTH R5 ROOT" +# Serial: 9009899650740120186 +# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 +# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 +# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Label: "SSL.com Root Certification Authority RSA" +# Serial: 8875640296558310041 +# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 +# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb +# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority RSA R2" +# Serial: 6248227494352943350 +# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 +# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a +# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority ECC" +# Serial: 3182246526754555285 +# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 +# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d +# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign Root CA - G1" +# Serial: 235931866688319308814040 +# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac +# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c +# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign ECC Root CA - G3" +# Serial: 287880440101571086945156 +# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 +# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 +# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Label: "emSign Root CA - C1" +# Serial: 825510296613316004955058 +# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 +# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 +# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Label: "emSign ECC Root CA - C3" +# Serial: 582948710642506000014504 +# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 +# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 +# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Label: "Hongkong Post Root CA 3" +# Serial: 46170865288971385588281144162979347873371282084 +# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 +# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 +# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL +BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ +SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n +a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5 +NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT +CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u +Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO +dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI +VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV +9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY +2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY +vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt +bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb +x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+ +l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK +TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj +Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw +DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG +7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk +MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr +gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk +GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS +3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm +Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+ +l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c +JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP +L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa +LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG +mpv0 +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G4" +# Serial: 289383649854506086828220374796556676440 +# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88 +# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01 +# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft ECC Root Certificate Authority 2017" +# Serial: 136839042543790627607696632466672567020 +# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67 +# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5 +# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02 +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD +VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy +b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR +ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb +hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 +FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV +L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB +iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft RSA Root Certificate Authority 2017" +# Serial: 40975477897264996090493496164228220339 +# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47 +# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74 +# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0 +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl +MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N +aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ +Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 +ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 +HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm +gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ +jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc +aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG +YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 +W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K +UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH ++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q +W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC +LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC +gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 +tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh +SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 +TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 +pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR +xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp +GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 +dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN +AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB +RA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Label: "e-Szigno Root CA 2017" +# Serial: 411379200276854331539784714 +# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98 +# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1 +# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99 +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV +BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk +LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv +b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ +BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg +THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v +IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv +xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H +Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB +eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo +jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ ++efcMQ== +-----END CERTIFICATE----- + +# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Label: "certSIGN Root CA G2" +# Serial: 313609486401300475190 +# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7 +# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32 +# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g +Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ +BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ +R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF +dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw +vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ +uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp +n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs +cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW +xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P +rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF +DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx +DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy +LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C +eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ +d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq +kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl +qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 +OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c +NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk +ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO +pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj +03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk +PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE +1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX +QRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global Certification Authority" +# Serial: 1846098327275375458322922162 +# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e +# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5 +# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8 +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw +CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x +ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 +c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx +OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI +SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn +swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu +7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 +1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW +80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP +JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l +RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw +hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 +coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc +BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n +twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W +0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe +uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q +lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB +aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE +sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT +MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe +qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh +VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 +h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 +EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK +yeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P256 Certification Authority" +# Serial: 4151900041497450638097112925 +# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54 +# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf +# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4 +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN +FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w +DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw +CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh +DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P384 Certification Authority" +# Serial: 2704997926503831671788816187 +# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6 +# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2 +# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97 +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ +j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF +1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G +A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 +AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC +MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu +Sw== +-----END CERTIFICATE----- + +# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Label: "NAVER Global Root Certification Authority" +# Serial: 9013692873798656336226253319739695165984492813 +# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b +# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 +# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- + +# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" +# Serial: 131542671362353147877283741781055151509 +# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb +# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a +# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Label: "GlobalSign Root R46" +# Serial: 1552617688466950547958867513931858518042577 +# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef +# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 +# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Label: "GlobalSign Root E46" +# Serial: 1552617690338932563915843282459653771421763 +# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f +# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 +# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Label: "GLOBALTRUST 2020" +# Serial: 109160994242082918454945253 +# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8 +# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2 +# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Label: "ANF Secure Server Root CA" +# Serial: 996390341000653745 +# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 +# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 +# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV +BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk +YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV +BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN +MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF +UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD +VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v +dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj +cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q +yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH +2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX +H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL +zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR +p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz +W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/ +SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn +LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3 +n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B +u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L +9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej +rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK +pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0 +vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq +OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ +/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9 +2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI ++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2 +MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo +tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE----- + +# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum EC-384 CA" +# Serial: 160250656287871593594747141429395092468 +# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 +# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed +# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Root CA" +# Serial: 40870380103424195783807378461123655149 +# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 +# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 +# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd +-----BEGIN CERTIFICATE----- +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 +MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu +MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV +BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw +MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg +U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ +n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q +p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq +NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF +8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3 +HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa +mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi +7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF +ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P +qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ +v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6 +Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD +ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4 +WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo +zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR +5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ +GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf +5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq +0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D +P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM +qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP +0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf +E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE----- + +# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Label: "TunTrust Root CA" +# Serial: 108534058042236574382096126452369648152337120275 +# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4 +# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb +# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg +Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv +b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG +EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u +IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ +n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd +2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF +VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ +GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF +li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU +r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 +eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb +MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg +jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB +7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW +5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE +ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z +xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu +QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 +FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH +22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP +xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn +dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 +Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b +nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ +CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH +u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj +d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS RSA Root CA 2021" +# Serial: 76817823531813593706434026085292783742 +# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91 +# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d +# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg +Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL +MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l +mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE +4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv +a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M +pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw +Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b +LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY +AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB +AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq +E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr +W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ +CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU +X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 +f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja +H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP +JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P +zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt +jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 +/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT +BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 +aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW +xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU +63ZTGI0RmLo= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS ECC Root CA 2021" +# Serial: 137515985548005187474074462014555733966 +# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0 +# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48 +# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01 +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw +CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh +cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v +dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG +A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 +KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y +STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD +AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw +SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN +nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 1977337328857672817 +# MD5 Fingerprint: 4e:6e:9b:54:4c:ca:b7:fa:48:e4:90:b1:15:4b:1c:a3 +# SHA1 Fingerprint: 0b:be:c2:27:22:49:cb:39:aa:db:35:5c:53:e3:8c:ae:78:ff:b6:fe +# SHA256 Fingerprint: 57:de:05:83:ef:d2:b2:6e:03:61:da:99:da:9d:f4:64:8d:ef:7e:e8:44:1c:3b:72:8a:fa:9b:cd:e0:f9:b2:6a +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 +MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc +tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd +IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC +AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw +ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m +iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF +Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ +hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P +Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE +EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV +1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t +CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR +5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw +f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 +ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK +GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- + +# Issuer: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. +# Subject: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. +# Label: "vTrus ECC Root CA" +# Serial: 630369271402956006249506845124680065938238527194 +# MD5 Fingerprint: de:4b:c1:f5:52:8c:9b:43:e1:3e:8f:55:54:17:8d:85 +# SHA1 Fingerprint: f6:9c:db:b0:fc:f6:02:13:b6:52:32:a6:a3:91:3f:16:70:da:c3:e1 +# SHA256 Fingerprint: 30:fb:ba:2c:32:23:8e:2a:98:54:7a:f9:79:31:e5:50:42:8b:9b:3f:1c:8e:eb:66:33:dc:fa:86:c5:b2:7d:d3 +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw +RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY +BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz +MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u +LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 +v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd +e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw +V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA +AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG +GJTO +-----END CERTIFICATE----- + +# Issuer: CN=vTrus Root CA O=iTrusChina Co.,Ltd. +# Subject: CN=vTrus Root CA O=iTrusChina Co.,Ltd. +# Label: "vTrus Root CA" +# Serial: 387574501246983434957692974888460947164905180485 +# MD5 Fingerprint: b8:c9:37:df:fa:6b:31:84:64:c5:ea:11:6a:1b:75:fc +# SHA1 Fingerprint: 84:1a:69:fb:f5:cd:1a:25:34:13:3d:e3:f8:fc:b8:99:d0:c9:14:b7 +# SHA256 Fingerprint: 8a:71:de:65:59:33:6f:42:6c:26:e5:38:80:d0:0d:88:a1:8d:a4:c6:a9:1f:0d:cb:61:94:e2:06:c5:c9:63:87 +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL +BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x +FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx +MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s +THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc +IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU +AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ +GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 +8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH +flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt +J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim +0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN +pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ +UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW +OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB +AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet +8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j +bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM +Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv +TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS +S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr +I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 +b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB +UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P +Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven +sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X2 O=Internet Security Research Group +# Subject: CN=ISRG Root X2 O=Internet Security Research Group +# Label: "ISRG Root X2" +# Serial: 87493402998870891108772069816698636114 +# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5 +# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af +# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70 +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw +CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg +R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 +MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT +ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW ++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 +ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI +zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW +tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 +/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- + +# Issuer: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. +# Subject: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. +# Label: "HiPKI Root CA - G1" +# Serial: 60966262342023497858655262305426234976 +# MD5 Fingerprint: 69:45:df:16:65:4b:e8:68:9a:8f:76:5f:ff:80:9e:d3 +# SHA1 Fingerprint: 6a:92:e4:a8:ee:1b:ec:96:45:37:e3:29:57:49:cd:96:e3:e5:d2:60 +# SHA256 Fingerprint: f0:15:ce:3c:c2:39:bf:ef:06:4b:e9:f1:d2:c4:17:e1:a0:26:4a:0a:94:be:1f:0c:8d:12:18:64:eb:69:49:cc +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa +Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 +YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw +qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv +Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 +lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz +Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ +KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK +FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj +HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr +y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ +/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM +a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 +fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG +SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc +SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza +ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc +XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg +iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho +L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF +Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr +kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ +vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU +YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 159662223612894884239637590694 +# MD5 Fingerprint: 26:29:f8:6d:e1:88:bf:a2:65:7f:aa:c4:cd:0f:7f:fc +# SHA1 Fingerprint: 6b:a0:b0:98:e1:71:ef:5a:ad:fe:48:15:80:77:10:f4:bd:6f:0b:28 +# SHA256 Fingerprint: b0:85:d7:0b:96:4f:19:1a:73:e4:af:0d:54:ae:7a:0e:07:aa:fd:af:9b:71:dd:08:62:13:8a:b7:32:5a:24:a2 +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD +VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw +MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g +UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx +uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV +HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ ++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 +bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 159662320309726417404178440727 +# MD5 Fingerprint: 05:fe:d0:bf:71:a8:a3:76:63:da:01:e0:d8:52:dc:40 +# SHA1 Fingerprint: e5:8c:1c:c4:91:3b:38:63:4b:e9:10:6e:e3:ad:8e:6b:9d:d9:81:4a +# SHA256 Fingerprint: d9:47:43:2a:bd:e7:b7:fa:90:fc:2e:6b:59:10:1b:12:80:e0:e1:c7:e4:e4:0f:a3:c6:88:7f:ff:57:a7:f4:cf +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 159662449406622349769042896298 +# MD5 Fingerprint: 1e:39:c0:53:e6:1e:29:82:0b:ca:52:55:36:5d:57:dc +# SHA1 Fingerprint: 9a:44:49:76:32:db:de:fa:d0:bc:fb:5a:7b:17:bd:9e:56:09:24:94 +# SHA256 Fingerprint: 8d:25:cd:97:22:9d:bf:70:35:6b:da:4e:b3:cc:73:40:31:e2:4c:f0:0f:af:cf:d3:2d:c7:6e:b5:84:1c:7e:a8 +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 159662495401136852707857743206 +# MD5 Fingerprint: 3e:e7:9d:58:02:94:46:51:94:e5:e0:22:4a:8b:e7:73 +# SHA1 Fingerprint: ed:e5:71:80:2b:c8:92:b9:5b:83:3c:d2:32:68:3f:09:cd:a0:1e:46 +# SHA256 Fingerprint: 34:d8:a7:3e:e2:08:d9:bc:db:0d:95:65:20:93:4b:4e:40:e6:94:82:59:6e:8b:6f:73:c8:42:6b:01:0a:6f:48 +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G +jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 +4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 +VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm +ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 159662532700760215368942768210 +# MD5 Fingerprint: 43:96:83:77:19:4d:76:b3:9d:65:52:e4:1d:22:a5:e8 +# SHA1 Fingerprint: 77:d3:03:67:b5:e0:0c:15:f6:0c:38:61:df:7c:e1:3b:92:46:4d:47 +# SHA256 Fingerprint: 34:9d:fa:40:58:c5:e2:63:12:3b:39:8a:e7:95:57:3c:4e:13:13:c8:3f:e6:8f:93:55:6c:d5:e8:03:1b:3c:7d +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +# Issuer: CN=Telia Root CA v2 O=Telia Finland Oyj +# Subject: CN=Telia Root CA v2 O=Telia Finland Oyj +# Label: "Telia Root CA v2" +# Serial: 7288924052977061235122729490515358 +# MD5 Fingerprint: 0e:8f:ac:aa:82:df:85:b1:f4:dc:10:1c:fc:99:d9:48 +# SHA1 Fingerprint: b9:99:cd:d1:73:50:8a:c4:47:05:08:9c:8c:88:fb:be:a0:2b:40:cd +# SHA256 Fingerprint: 24:2b:69:74:2f:cb:1e:5b:2a:bf:98:89:8b:94:57:21:87:54:4e:5b:4d:99:11:78:65:73:62:1f:6a:74:b8:2c +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx +CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE +AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 +NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ +MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq +AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 +vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 +lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD +n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT +7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o +6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC +TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 +WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R +DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI +pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj +YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy +rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi +0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM +A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS +SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K +TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF +6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er +3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt +Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT +VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW +ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA +rBPuUBQemMc= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH +# Subject: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH +# Label: "D-TRUST BR Root CA 1 2020" +# Serial: 165870826978392376648679885835942448534 +# MD5 Fingerprint: b5:aa:4b:d5:ed:f7:e3:55:2e:8f:72:0a:f3:75:b8:ed +# SHA1 Fingerprint: 1f:5b:98:f0:e3:b5:f7:74:3c:ed:e6:b0:36:7d:32:cd:f4:09:41:67 +# SHA256 Fingerprint: e5:9a:aa:81:60:09:c2:2b:ff:5b:25:ba:d3:7d:f3:06:f0:49:79:7c:1f:81:d8:5a:b0:89:e6:57:bd:8f:00:44 +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 +NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS +zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 +QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ +VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW +wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV +dWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH +# Subject: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH +# Label: "D-TRUST EV Root CA 1 2020" +# Serial: 126288379621884218666039612629459926992 +# MD5 Fingerprint: 8c:2d:9d:70:9f:48:99:11:06:11:fb:e9:cb:30:c0:6e +# SHA1 Fingerprint: 61:db:8c:21:59:69:03:90:d8:7c:9c:12:86:54:cf:9d:3d:f4:dd:07 +# SHA256 Fingerprint: 08:17:0d:1a:a3:64:53:90:1a:2f:95:92:45:e3:47:db:0c:8d:37:ab:aa:bc:56:b8:1a:a1:00:dc:95:89:70:db +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 +NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC +/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD +wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 +OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA +y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb +gfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. +# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. +# Label: "DigiCert TLS ECC P384 Root G5" +# Serial: 13129116028163249804115411775095713523 +# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed +# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee +# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05 +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp +Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 +MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS +7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp +0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS +B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ +LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 +DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. +# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. +# Label: "DigiCert TLS RSA4096 Root G5" +# Serial: 11930366277458970227240571539258396554 +# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1 +# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35 +# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75 +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT +HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN +NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs +IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ +ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 +2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp +wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM +pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD +nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po +sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx +Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd +Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX +KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe +XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL +tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv +TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H +PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF +O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ +REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik +AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv +/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ +p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw +MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF +qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK +ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +# Issuer: CN=Certainly Root R1 O=Certainly +# Subject: CN=Certainly Root R1 O=Certainly +# Label: "Certainly Root R1" +# Serial: 188833316161142517227353805653483829216 +# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12 +# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af +# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw +PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy +dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 +YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 +1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT +vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed +aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 +1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 +r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 +cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ +wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ +6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA +2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH +Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR +eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u +d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr +PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi +1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd +rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di +taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 +lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj +yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn +Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy +yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n +wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 +OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +# Issuer: CN=Certainly Root E1 O=Certainly +# Subject: CN=Certainly Root E1 O=Certainly +# Label: "Certainly Root E1" +# Serial: 8168531406727139161245376702891150584 +# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9 +# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b +# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2 +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu +bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ +BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s +eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK ++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 +QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 +hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm +ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG +BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Subject: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Label: "E-Tugra Global Root CA RSA v3" +# Serial: 75951268308633135324246244059508261641472512052 +# MD5 Fingerprint: 22:be:10:f6:c2:f8:03:88:73:5f:33:29:47:28:47:a4 +# SHA1 Fingerprint: e9:a8:5d:22:14:52:1c:5b:aa:0a:b4:be:24:6a:23:8a:c9:ba:e2:a9 +# SHA256 Fingerprint: ef:66:b0:b1:0a:3c:db:9f:2e:36:48:c7:6b:d2:af:18:ea:d2:bf:e6:f1:17:65:5e:28:c4:06:0d:a1:a3:f4:c2 +-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUt +VHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYw +JAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgw +OTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMG +QW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBD +QSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J7 +7gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscx +uj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd8 +7jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/ +rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFL +l+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bG +wzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4 +znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBO +M/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK +5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAH +nnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2Amo +DVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSy +tK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ +6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18 +Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ +3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPk +vmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn9 +9t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQ +mhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YA +VSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF +9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscM +moi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8 +bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Subject: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Label: "E-Tugra Global Root CA ECC v3" +# Serial: 218504919822255052842371958738296604628416471745 +# MD5 Fingerprint: 46:bc:81:bb:f1:b5:1e:f7:4b:96:bc:14:e2:e7:27:64 +# SHA1 Fingerprint: 8a:2f:af:57:53:b1:b0:e6:a1:04:ec:5b:6a:69:71:6d:f6:1c:e2:84 +# SHA256 Fingerprint: 87:3f:46:85:fa:7f:56:36:25:25:2e:6d:36:bc:d7:f1:6f:c2:49:51:f2:64:e4:7e:1b:95:4f:49:08:cd:ca:13 +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw +gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn +cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD +VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2 +NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r +YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh +IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF +Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ +KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK +fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB +Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C +MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp +ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6 +7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx +vmjkI6TZraE3 +-----END CERTIFICATE----- + +# Issuer: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. +# Subject: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. +# Label: "Security Communication RootCA3" +# Serial: 16247922307909811815 +# MD5 Fingerprint: 1c:9a:16:ff:9e:5c:e0:4d:8a:14:01:f4:35:5d:29:26 +# SHA1 Fingerprint: c3:03:c8:22:74:92:e5:61:a2:9c:5f:79:91:2b:1e:44:13:91:30:3a +# SHA256 Fingerprint: 24:a5:5c:2a:b0:51:44:2d:06:17:76:65:41:23:9a:4a:d0:32:d7:c5:51:75:aa:34:ff:de:2f:bc:4f:5c:52:94 +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV +BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw +JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 +MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg +Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r +CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA +lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG +TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 +9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 +8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 +g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we +GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst ++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M +0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ +T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw +HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA +FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd +9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI +UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ +OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke +gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf +iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV +nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD +2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// +1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad +TdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE----- + +# Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. +# Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. +# Label: "Security Communication ECC RootCA1" +# Serial: 15446673492073852651 +# MD5 Fingerprint: 7e:43:b0:92:68:ec:05:43:4c:98:ab:5d:35:2e:7e:86 +# SHA1 Fingerprint: b8:0e:26:a9:bf:d2:b2:3b:c0:ef:46:c9:ba:c7:bb:f6:1d:0d:41:41 +# SHA256 Fingerprint: e7:4f:bd:a5:5b:d5:64:c4:73:a3:6b:44:1a:a7:99:c8:a6:8e:07:74:40:e8:28:8b:9f:a1:e5:0e:4b:ba:ca:11 +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT +AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD +VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx +NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT +HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 +IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl +dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK +ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu +9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O +be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= +-----END CERTIFICATE----- diff --git a/axios-example/lib/python3.10/site-packages/certifi/core.py b/axios-example/lib/python3.10/site-packages/certifi/core.py new file mode 100644 index 0000000..de02898 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/certifi/core.py @@ -0,0 +1,108 @@ +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem or its contents. +""" +import sys + + +if sys.version_info >= (3, 11): + + from importlib.resources import as_file, files + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the file + # in cases where we're inside of a zipimport situation until someone + # actually calls where(), but we don't want to re-extract the file + # on every call of where(), so we'll do it once then store it in a + # global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you to + # manage the cleanup of this file, so it doesn't actually return a + # path, it returns a context manager that will give you the path + # when you enter it and will do any cleanup when you leave it. In + # the common case of not needing a temporary file, it will just + # return the file system location and the __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + + return _CACERT_PATH + + def contents() -> str: + return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") + +elif sys.version_info >= (3, 7): + + from importlib.resources import path as get_path, read_text + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the + # file in cases where we're inside of a zipimport situation until + # someone actually calls where(), but we don't want to re-extract + # the file on every call of where(), so we'll do it once then store + # it in a global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you + # to manage the cleanup of this file, so it doesn't actually + # return a path, it returns a context manager that will give + # you the path when you enter it and will do any cleanup when + # you leave it. In the common case of not needing a temporary + # file, it will just return the file system location and the + # __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = get_path("certifi", "cacert.pem") + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + + return _CACERT_PATH + + def contents() -> str: + return read_text("certifi", "cacert.pem", encoding="ascii") + +else: + import os + import types + from typing import Union + + Package = Union[types.ModuleType, str] + Resource = Union[str, "os.PathLike"] + + # This fallback will work for Python versions prior to 3.7 that lack the + # importlib.resources module but relies on the existing `where` function + # so won't address issues with environments like PyOxidizer that don't set + # __file__ on modules. + def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict' + ) -> str: + with open(where(), encoding=encoding) as data: + return data.read() + + # If we don't have importlib.resources, then we will just do the old logic + # of assuming we're on the filesystem and munge the path directly. + def where() -> str: + f = os.path.dirname(__file__) + + return os.path.join(f, "cacert.pem") + + def contents() -> str: + return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/axios-example/lib/python3.10/site-packages/certifi/py.typed b/axios-example/lib/python3.10/site-packages/certifi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/LICENSE new file mode 100644 index 0000000..ad82355 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 TAHRI Ahmed R. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/METADATA new file mode 100644 index 0000000..c6ebd7d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/METADATA @@ -0,0 +1,269 @@ +Metadata-Version: 2.1 +Name: charset-normalizer +Version: 2.1.1 +Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. +Home-page: https://github.com/ousret/charset_normalizer +Author: Ahmed TAHRI @Ousret +Author-email: ahmed.tahri@cloudnursery.dev +License: MIT +Project-URL: Bug Reports, https://github.com/Ousret/charset_normalizer/issues +Project-URL: Documentation, https://charset-normalizer.readthedocs.io/en/latest +Keywords: encoding,i18n,txt,text,charset,charset-detector,normalization,unicode,chardet +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: MIT License +Classifier: Intended Audience :: Developers +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Text Processing :: Linguistic +Classifier: Topic :: Utilities +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Typing :: Typed +Requires-Python: >=3.6.0 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: unicode_backport +Requires-Dist: unicodedata2 ; extra == 'unicode_backport' + + +

Charset Detection, for Everyone 👋

+ +

+ The Real First Universal Charset Detector
+ + + + + + + + Download Count Total + +

+ +> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`, +> I'm trying to resolve the issue by taking a new approach. +> All IANA character set names for which the Python core library provides codecs are supported. + +

+ >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< +

+ +This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. + +| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | +| ------------- | :-------------: | :------------------: | :------------------: | +| `Fast` | ❌
| ✅
| ✅
| +| `Universal**` | ❌ | ✅ | ❌ | +| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ | +| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | +| `License` | LGPL-2.1
_restrictive_ | MIT | MPL-1.1
_restrictive_ | +| `Native Python` | ✅ | ✅ | ❌ | +| `Detect spoken language` | ❌ | ✅ | N/A | +| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ | +| `Whl Size` | 193.6 kB | 39.5 kB | ~200 kB | +| `Supported Encoding` | 33 | :tada: [93](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 + +

+Reading Normalized TextCat Reading Text + +*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
+Did you got there because of the logs? See [https://charset-normalizer.readthedocs.io/en/latest/user/miscellaneous.html](https://charset-normalizer.readthedocs.io/en/latest/user/miscellaneous.html) + +## ⭐ Your support + +*Fork, test-it, star-it, submit your ideas! We do listen.* + +## ⚡ Performance + +This package offer better performance than its counterpart Chardet. Here are some numbers. + +| Package | Accuracy | Mean per file (ms) | File per sec (est) | +| ------------- | :-------------: | :------------------: | :------------------: | +| [chardet](https://github.com/chardet/chardet) | 86 % | 200 ms | 5 file/sec | +| charset-normalizer | **98 %** | **39 ms** | 26 file/sec | + +| Package | 99th percentile | 95th percentile | 50th percentile | +| ------------- | :-------------: | :------------------: | :------------------: | +| [chardet](https://github.com/chardet/chardet) | 1200 ms | 287 ms | 23 ms | +| charset-normalizer | 400 ms | 200 ms | 15 ms | + +Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload. + +> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. +> And yes, these results might change at any time. The dataset can be updated to include more files. +> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. +> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability +> (eg. Supported Encoding) Challenge-them if you want. + +[cchardet](https://github.com/PyYoshi/cChardet) is a non-native (cpp binding) and unmaintained faster alternative with +a better accuracy than chardet but lower than this package. If speed is the most important factor, you should try it. + +## ✨ Installation + +Using PyPi for latest stable +```sh +pip install charset-normalizer -U +``` + +If you want a more up-to-date `unicodedata` than the one available in your Python setup. +```sh +pip install charset-normalizer[unicode_backport] -U +``` + +## 🚀 Basic Usage + +### CLI +This package comes with a CLI. + +``` +usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] + file [file ...] + +The Real First Universal Charset Detector. Discover originating encoding used +on text file. Normalize text to unicode. + +positional arguments: + files File(s) to be analysed + +optional arguments: + -h, --help show this help message and exit + -v, --verbose Display complementary information about file if any. + Stdout will contain logs about the detection process. + -a, --with-alternative + Output complementary possibilities if any. Top-level + JSON WILL be a list. + -n, --normalize Permit to normalize input file. If not set, program + does not write anything. + -m, --minimal Only output the charset detected to STDOUT. Disabling + JSON output. + -r, --replace Replace file when trying to normalize it instead of + creating a new one. + -f, --force Replace file without asking if you are sure, use this + flag with caution. + -t THRESHOLD, --threshold THRESHOLD + Define a custom maximum amount of chaos allowed in + decoded content. 0. <= chaos <= 1. + --version Show version information and exit. +``` + +```bash +normalizer ./data/sample.1.fr.srt +``` + +:tada: Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. + +```json +{ + "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", + "encoding": "cp1252", + "encoding_aliases": [ + "1252", + "windows_1252" + ], + "alternative_encodings": [ + "cp1254", + "cp1256", + "cp1258", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + "mbcs" + ], + "language": "French", + "alphabets": [ + "Basic Latin", + "Latin-1 Supplement" + ], + "has_sig_or_bom": false, + "chaos": 0.149, + "coherence": 97.152, + "unicode_path": null, + "is_preferred": true +} +``` + +### Python +*Just print out normalized text* +```python +from charset_normalizer import from_path + +results = from_path('./my_subtitle.srt') + +print(str(results.best())) +``` + +*Normalize any text file* +```python +from charset_normalizer import normalize +try: + normalize('./my_subtitle.srt') # should write to disk my_subtitle-***.srt +except IOError as e: + print('Sadly, we are unable to perform charset normalization.', str(e)) +``` + +*Upgrade your code without effort* +```python +from charset_normalizer import detect +``` + +The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. + +See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) + +## 😇 Why + +When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a +reliable alternative using a completely different method. Also! I never back down on a good challenge! + +I **don't care** about the **originating charset** encoding, because **two different tables** can +produce **two identical rendered string.** +What I want is to get readable text, the best I can. + +In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 + +Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. + +## 🍰 How + + - Discard all charset encoding table that could not fit the binary content. + - Measure chaos, or the mess once opened (by chunks) with a corresponding charset encoding. + - Extract matches with the lowest mess detected. + - Additionally, we measure coherence / probe for a language. + +**Wait a minute**, what is chaos/mess and coherence according to **YOU ?** + +*Chaos :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then +**I established** some ground rules about **what is obvious** when **it seems like** a mess. + I know that my interpretation of what is chaotic is very subjective, feel free to contribute in order to + improve or rewrite it. + +*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought +that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. + +## ⚡ Known limitations + + - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) + - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. + +## 👤 Contributing + +Contributions, issues and feature requests are very much welcome.
+Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. + +## 📝 License + +Copyright © 2019 [Ahmed TAHRI @Ousret](https://github.com/Ousret).
+This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. + +Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/RECORD new file mode 100644 index 0000000..e16f577 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/RECORD @@ -0,0 +1,33 @@ +../../../bin/normalizer,sha256=Lcm5bPOqQIc8CsHM03L1FzPB4l7gxc07RJUqGYqyhsk,280 +charset_normalizer-2.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +charset_normalizer-2.1.1.dist-info/LICENSE,sha256=6zGgxaT7Cbik4yBV0lweX5w1iidS_vPNcgIT0cz-4kE,1070 +charset_normalizer-2.1.1.dist-info/METADATA,sha256=C99l12g4d1E9_UiW-mqPCWx7v2M_lYGWxy1GTOjXSsA,11942 +charset_normalizer-2.1.1.dist-info/RECORD,, +charset_normalizer-2.1.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +charset_normalizer-2.1.1.dist-info/entry_points.txt,sha256=uYo8aIGLWv8YgWfSna5HnfY_En4pkF1w4bgawNAXzP0,76 +charset_normalizer-2.1.1.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19 +charset_normalizer/__init__.py,sha256=jGhhf1IcOgCpZsr593E9fPvjWKnflVqHe_LwkOJjInU,1790 +charset_normalizer/__pycache__/__init__.cpython-310.pyc,, +charset_normalizer/__pycache__/api.cpython-310.pyc,, +charset_normalizer/__pycache__/cd.cpython-310.pyc,, +charset_normalizer/__pycache__/constant.cpython-310.pyc,, +charset_normalizer/__pycache__/legacy.cpython-310.pyc,, +charset_normalizer/__pycache__/md.cpython-310.pyc,, +charset_normalizer/__pycache__/models.cpython-310.pyc,, +charset_normalizer/__pycache__/utils.cpython-310.pyc,, +charset_normalizer/__pycache__/version.cpython-310.pyc,, +charset_normalizer/api.py,sha256=euVPmjAMbjpqhEHPjfKtyy1mK52U0TOUBUQgM_Qy6eE,19191 +charset_normalizer/assets/__init__.py,sha256=r7aakPaRIc2FFG2mw2V8NOTvkl25_euKZ3wPf5SAVa4,15222 +charset_normalizer/assets/__pycache__/__init__.cpython-310.pyc,, +charset_normalizer/cd.py,sha256=Pxdkbn4cy0iZF42KTb1FiWIqqKobuz_fDjGwc6JMNBc,10811 +charset_normalizer/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +charset_normalizer/cli/__pycache__/__init__.cpython-310.pyc,, +charset_normalizer/cli/__pycache__/normalizer.cpython-310.pyc,, +charset_normalizer/cli/normalizer.py,sha256=FmD1RXeMpRBg_mjR0MaJhNUpM2qZ8wz2neAE7AayBeg,9521 +charset_normalizer/constant.py,sha256=NgU-pY8JH2a9lkVT8oKwAFmIUYNKOuSBwZgF9MrlNCM,19157 +charset_normalizer/legacy.py,sha256=XKeZOts_HdYQU_Jb3C9ZfOjY2CiUL132k9_nXer8gig,3384 +charset_normalizer/md.py,sha256=pZP8IVpSC82D8INA9Tf_y0ijJSRI-UIncZvLdfTWEd4,17642 +charset_normalizer/models.py,sha256=i68YdlSLTEI3EEBVXq8TLNAbyyjrLC2OWszc-OBAk9I,13167 +charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +charset_normalizer/utils.py,sha256=ykOznhcAeH-ODLBWJuI7t1nbwa1SAfN_bDYTCJGyh4U,11771 +charset_normalizer/version.py,sha256=_eh2MA3qS__IajlePQxKBmlw6zaBDvPYlLdEgxgIojw,79 diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/entry_points.txt b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/entry_points.txt new file mode 100644 index 0000000..a06d360 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +normalizer = charset_normalizer.cli.normalizer:cli_detect diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/top_level.txt new file mode 100644 index 0000000..66958f0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer-2.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +charset_normalizer diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/__init__.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/__init__.py new file mode 100644 index 0000000..2dcaf56 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/__init__.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +""" +Charset-Normalizer +~~~~~~~~~~~~~~ +The Real First Universal Charset Detector. +A library that helps you read text from an unknown charset encoding. +Motivated by chardet, This package is trying to resolve the issue by taking a new approach. +All IANA character set names for which the Python core library provides codecs are supported. + +Basic usage: + >>> from charset_normalizer import from_bytes + >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) + >>> best_guess = results.best() + >>> str(best_guess) + 'Bсеки човек има право на образование. Oбразованието!' + +Others methods and usages are available - see the full documentation +at . +:copyright: (c) 2021 by Ahmed TAHRI +:license: MIT, see LICENSE for more details. +""" +import logging + +from .api import from_bytes, from_fp, from_path, normalize +from .legacy import ( + CharsetDetector, + CharsetDoctor, + CharsetNormalizerMatch, + CharsetNormalizerMatches, + detect, +) +from .models import CharsetMatch, CharsetMatches +from .utils import set_logging_handler +from .version import VERSION, __version__ + +__all__ = ( + "from_fp", + "from_path", + "from_bytes", + "normalize", + "detect", + "CharsetMatch", + "CharsetMatches", + "CharsetNormalizerMatch", + "CharsetNormalizerMatches", + "CharsetDetector", + "CharsetDoctor", + "__version__", + "VERSION", + "set_logging_handler", +) + +# Attach a NullHandler to the top level logger by default +# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library + +logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/api.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/api.py new file mode 100644 index 0000000..72907f9 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/api.py @@ -0,0 +1,584 @@ +import logging +import warnings +from os import PathLike +from os.path import basename, splitext +from typing import Any, BinaryIO, List, Optional, Set + +from .cd import ( + coherence_ratio, + encoding_languages, + mb_encoding_languages, + merge_coherence_ratios, +) +from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE +from .md import mess_ratio +from .models import CharsetMatch, CharsetMatches +from .utils import ( + any_specified_encoding, + cut_sequence_chunks, + iana_name, + identify_sig_or_bom, + is_cp_similar, + is_multi_byte_encoding, + should_strip_sig_or_bom, +) + +# Will most likely be controversial +# logging.addLevelName(TRACE, "TRACE") +logger = logging.getLogger("charset_normalizer") +explain_handler = logging.StreamHandler() +explain_handler.setFormatter( + logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") +) + + +def from_bytes( + sequences: bytes, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.2, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, +) -> CharsetMatches: + """ + Given a raw bytes sequence, return the best possibles charset usable to render str objects. + If there is no results, it is a strong indicator that the source is binary/not text. + By default, the process will extract 5 blocs of 512o each to assess the mess and coherence of a given sequence. + And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. + + The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page + but never take it for granted. Can improve the performance. + + You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that + purpose. + + This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. + By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' + toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. + Custom logging format and handler can be set manually. + """ + + if not isinstance(sequences, (bytearray, bytes)): + raise TypeError( + "Expected object of type bytes or bytearray, got: {0}".format( + type(sequences) + ) + ) + + if explain: + previous_logger_level: int = logger.level + logger.addHandler(explain_handler) + logger.setLevel(TRACE) + + length: int = len(sequences) + + if length == 0: + logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level or logging.WARNING) + return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) + + if cp_isolation is not None: + logger.log( + TRACE, + "cp_isolation is set. use this flag for debugging purpose. " + "limited list of encoding allowed : %s.", + ", ".join(cp_isolation), + ) + cp_isolation = [iana_name(cp, False) for cp in cp_isolation] + else: + cp_isolation = [] + + if cp_exclusion is not None: + logger.log( + TRACE, + "cp_exclusion is set. use this flag for debugging purpose. " + "limited list of encoding excluded : %s.", + ", ".join(cp_exclusion), + ) + cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] + else: + cp_exclusion = [] + + if length <= (chunk_size * steps): + logger.log( + TRACE, + "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", + steps, + chunk_size, + length, + ) + steps = 1 + chunk_size = length + + if steps > 1 and length / steps < chunk_size: + chunk_size = int(length / steps) + + is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE + is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE + + if is_too_small_sequence: + logger.log( + TRACE, + "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( + length + ), + ) + elif is_too_large_sequence: + logger.log( + TRACE, + "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( + length + ), + ) + + prioritized_encodings: List[str] = [] + + specified_encoding: Optional[str] = ( + any_specified_encoding(sequences) if preemptive_behaviour else None + ) + + if specified_encoding is not None: + prioritized_encodings.append(specified_encoding) + logger.log( + TRACE, + "Detected declarative mark in sequence. Priority +1 given for %s.", + specified_encoding, + ) + + tested: Set[str] = set() + tested_but_hard_failure: List[str] = [] + tested_but_soft_failure: List[str] = [] + + fallback_ascii: Optional[CharsetMatch] = None + fallback_u8: Optional[CharsetMatch] = None + fallback_specified: Optional[CharsetMatch] = None + + results: CharsetMatches = CharsetMatches() + + sig_encoding, sig_payload = identify_sig_or_bom(sequences) + + if sig_encoding is not None: + prioritized_encodings.append(sig_encoding) + logger.log( + TRACE, + "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", + len(sig_payload), + sig_encoding, + ) + + prioritized_encodings.append("ascii") + + if "utf_8" not in prioritized_encodings: + prioritized_encodings.append("utf_8") + + for encoding_iana in prioritized_encodings + IANA_SUPPORTED: + + if cp_isolation and encoding_iana not in cp_isolation: + continue + + if cp_exclusion and encoding_iana in cp_exclusion: + continue + + if encoding_iana in tested: + continue + + tested.add(encoding_iana) + + decoded_payload: Optional[str] = None + bom_or_sig_available: bool = sig_encoding == encoding_iana + strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( + encoding_iana + ) + + if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: + logger.log( + TRACE, + "Encoding %s wont be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", + encoding_iana, + ) + continue + + try: + is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) + except (ModuleNotFoundError, ImportError): + logger.log( + TRACE, + "Encoding %s does not provide an IncrementalDecoder", + encoding_iana, + ) + continue + + try: + if is_too_large_sequence and is_multi_byte_decoder is False: + str( + sequences[: int(50e4)] + if strip_sig_or_bom is False + else sequences[len(sig_payload) : int(50e4)], + encoding=encoding_iana, + ) + else: + decoded_payload = str( + sequences + if strip_sig_or_bom is False + else sequences[len(sig_payload) :], + encoding=encoding_iana, + ) + except (UnicodeDecodeError, LookupError) as e: + if not isinstance(e, LookupError): + logger.log( + TRACE, + "Code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + similar_soft_failure_test: bool = False + + for encoding_soft_failed in tested_but_soft_failure: + if is_cp_similar(encoding_iana, encoding_soft_failed): + similar_soft_failure_test = True + break + + if similar_soft_failure_test: + logger.log( + TRACE, + "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", + encoding_iana, + encoding_soft_failed, + ) + continue + + r_ = range( + 0 if not bom_or_sig_available else len(sig_payload), + length, + int(length / steps), + ) + + multi_byte_bonus: bool = ( + is_multi_byte_decoder + and decoded_payload is not None + and len(decoded_payload) < length + ) + + if multi_byte_bonus: + logger.log( + TRACE, + "Code page %s is a multi byte encoding table and it appear that at least one character " + "was encoded using n-bytes.", + encoding_iana, + ) + + max_chunk_gave_up: int = int(len(r_) / 4) + + max_chunk_gave_up = max(max_chunk_gave_up, 2) + early_stop_count: int = 0 + lazy_str_hard_failure = False + + md_chunks: List[str] = [] + md_ratios = [] + + try: + for chunk in cut_sequence_chunks( + sequences, + encoding_iana, + r_, + chunk_size, + bom_or_sig_available, + strip_sig_or_bom, + sig_payload, + is_multi_byte_decoder, + decoded_payload, + ): + md_chunks.append(chunk) + + md_ratios.append(mess_ratio(chunk, threshold)) + + if md_ratios[-1] >= threshold: + early_stop_count += 1 + + if (early_stop_count >= max_chunk_gave_up) or ( + bom_or_sig_available and strip_sig_or_bom is False + ): + break + except UnicodeDecodeError as e: # Lazy str loading may have missed something there + logger.log( + TRACE, + "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + early_stop_count = max_chunk_gave_up + lazy_str_hard_failure = True + + # We might want to check the sequence again with the whole content + # Only if initial MD tests passes + if ( + not lazy_str_hard_failure + and is_too_large_sequence + and not is_multi_byte_decoder + ): + try: + sequences[int(50e3) :].decode(encoding_iana, errors="strict") + except UnicodeDecodeError as e: + logger.log( + TRACE, + "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 + if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: + tested_but_soft_failure.append(encoding_iana) + logger.log( + TRACE, + "%s was excluded because of initial chaos probing. Gave up %i time(s). " + "Computed mean chaos is %f %%.", + encoding_iana, + early_stop_count, + round(mean_mess_ratio * 100, ndigits=3), + ) + # Preparing those fallbacks in case we got nothing. + if ( + encoding_iana in ["ascii", "utf_8", specified_encoding] + and not lazy_str_hard_failure + ): + fallback_entry = CharsetMatch( + sequences, encoding_iana, threshold, False, [], decoded_payload + ) + if encoding_iana == specified_encoding: + fallback_specified = fallback_entry + elif encoding_iana == "ascii": + fallback_ascii = fallback_entry + else: + fallback_u8 = fallback_entry + continue + + logger.log( + TRACE, + "%s passed initial chaos probing. Mean measured chaos is %f %%", + encoding_iana, + round(mean_mess_ratio * 100, ndigits=3), + ) + + if not is_multi_byte_decoder: + target_languages: List[str] = encoding_languages(encoding_iana) + else: + target_languages = mb_encoding_languages(encoding_iana) + + if target_languages: + logger.log( + TRACE, + "{} should target any language(s) of {}".format( + encoding_iana, str(target_languages) + ), + ) + + cd_ratios = [] + + # We shall skip the CD when its about ASCII + # Most of the time its not relevant to run "language-detection" on it. + if encoding_iana != "ascii": + for chunk in md_chunks: + chunk_languages = coherence_ratio( + chunk, 0.1, ",".join(target_languages) if target_languages else None + ) + + cd_ratios.append(chunk_languages) + + cd_ratios_merged = merge_coherence_ratios(cd_ratios) + + if cd_ratios_merged: + logger.log( + TRACE, + "We detected language {} using {}".format( + cd_ratios_merged, encoding_iana + ), + ) + + results.append( + CharsetMatch( + sequences, + encoding_iana, + mean_mess_ratio, + bom_or_sig_available, + cd_ratios_merged, + decoded_payload, + ) + ) + + if ( + encoding_iana in [specified_encoding, "ascii", "utf_8"] + and mean_mess_ratio < 0.1 + ): + logger.debug( + "Encoding detection: %s is most likely the one.", encoding_iana + ) + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([results[encoding_iana]]) + + if encoding_iana == sig_encoding: + logger.debug( + "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " + "the beginning of the sequence.", + encoding_iana, + ) + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([results[encoding_iana]]) + + if len(results) == 0: + if fallback_u8 or fallback_ascii or fallback_specified: + logger.log( + TRACE, + "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", + ) + + if fallback_specified: + logger.debug( + "Encoding detection: %s will be used as a fallback match", + fallback_specified.encoding, + ) + results.append(fallback_specified) + elif ( + (fallback_u8 and fallback_ascii is None) + or ( + fallback_u8 + and fallback_ascii + and fallback_u8.fingerprint != fallback_ascii.fingerprint + ) + or (fallback_u8 is not None) + ): + logger.debug("Encoding detection: utf_8 will be used as a fallback match") + results.append(fallback_u8) + elif fallback_ascii: + logger.debug("Encoding detection: ascii will be used as a fallback match") + results.append(fallback_ascii) + + if results: + logger.debug( + "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", + results.best().encoding, # type: ignore + len(results) - 1, + ) + else: + logger.debug("Encoding detection: Unable to determine any suitable charset.") + + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + + return results + + +def from_fp( + fp: BinaryIO, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but using a file pointer that is already ready. + Will not close the file pointer. + """ + return from_bytes( + fp.read(), + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + ) + + +def from_path( + path: "PathLike[Any]", + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. + Can raise IOError. + """ + with open(path, "rb") as fp: + return from_fp( + fp, + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + ) + + +def normalize( + path: "PathLike[Any]", + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, +) -> CharsetMatch: + """ + Take a (text-based) file path and try to create another file next to it, this time using UTF-8. + """ + warnings.warn( + "normalize is deprecated and will be removed in 3.0", + DeprecationWarning, + ) + + results = from_path( + path, + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + ) + + filename = basename(path) + target_extensions = list(splitext(filename)) + + if len(results) == 0: + raise IOError( + 'Unable to normalize "{}", no encoding charset seems to fit.'.format( + filename + ) + ) + + result = results.best() + + target_extensions[0] += "-" + result.encoding # type: ignore + + with open( + "{}".format(str(path).replace(filename, "".join(target_extensions))), "wb" + ) as fp: + fp.write(result.output()) # type: ignore + + return result # type: ignore diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/assets/__init__.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/assets/__init__.py new file mode 100644 index 0000000..3c33ba3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/assets/__init__.py @@ -0,0 +1,1122 @@ +# -*- coding: utf-8 -*- +from typing import Dict, List + +FREQUENCIES: Dict[str, List[str]] = { + "English": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "u", + "m", + "f", + "p", + "g", + "w", + "y", + "b", + "v", + "k", + "x", + "j", + "z", + "q", + ], + "German": [ + "e", + "n", + "i", + "r", + "s", + "t", + "a", + "d", + "h", + "u", + "l", + "g", + "o", + "c", + "m", + "b", + "f", + "k", + "w", + "z", + "p", + "v", + "ü", + "ä", + "ö", + "j", + ], + "French": [ + "e", + "a", + "s", + "n", + "i", + "t", + "r", + "l", + "u", + "o", + "d", + "c", + "p", + "m", + "é", + "v", + "g", + "f", + "b", + "h", + "q", + "à", + "x", + "è", + "y", + "j", + ], + "Dutch": [ + "e", + "n", + "a", + "i", + "r", + "t", + "o", + "d", + "s", + "l", + "g", + "h", + "v", + "m", + "u", + "k", + "c", + "p", + "b", + "w", + "j", + "z", + "f", + "y", + "x", + "ë", + ], + "Italian": [ + "e", + "i", + "a", + "o", + "n", + "l", + "t", + "r", + "s", + "c", + "d", + "u", + "p", + "m", + "g", + "v", + "f", + "b", + "z", + "h", + "q", + "è", + "à", + "k", + "y", + "ò", + ], + "Polish": [ + "a", + "i", + "o", + "e", + "n", + "r", + "z", + "w", + "s", + "c", + "t", + "k", + "y", + "d", + "p", + "m", + "u", + "l", + "j", + "ł", + "g", + "b", + "h", + "ą", + "ę", + "ó", + ], + "Spanish": [ + "e", + "a", + "o", + "n", + "s", + "r", + "i", + "l", + "d", + "t", + "c", + "u", + "m", + "p", + "b", + "g", + "v", + "f", + "y", + "ó", + "h", + "q", + "í", + "j", + "z", + "á", + ], + "Russian": [ + "о", + "а", + "е", + "и", + "н", + "с", + "т", + "р", + "в", + "л", + "к", + "м", + "д", + "п", + "у", + "г", + "я", + "ы", + "з", + "б", + "й", + "ь", + "ч", + "х", + "ж", + "ц", + ], + "Japanese": [ + "の", + "に", + "る", + "た", + "は", + "ー", + "と", + "し", + "を", + "で", + "て", + "が", + "い", + "ン", + "れ", + "な", + "年", + "ス", + "っ", + "ル", + "か", + "ら", + "あ", + "さ", + "も", + "り", + ], + "Portuguese": [ + "a", + "e", + "o", + "s", + "i", + "r", + "d", + "n", + "t", + "m", + "u", + "c", + "l", + "p", + "g", + "v", + "b", + "f", + "h", + "ã", + "q", + "é", + "ç", + "á", + "z", + "í", + ], + "Swedish": [ + "e", + "a", + "n", + "r", + "t", + "s", + "i", + "l", + "d", + "o", + "m", + "k", + "g", + "v", + "h", + "f", + "u", + "p", + "ä", + "c", + "b", + "ö", + "å", + "y", + "j", + "x", + ], + "Chinese": [ + "的", + "一", + "是", + "不", + "了", + "在", + "人", + "有", + "我", + "他", + "这", + "个", + "们", + "中", + "来", + "上", + "大", + "为", + "和", + "国", + "地", + "到", + "以", + "说", + "时", + "要", + "就", + "出", + "会", + ], + "Ukrainian": [ + "о", + "а", + "н", + "і", + "и", + "р", + "в", + "т", + "е", + "с", + "к", + "л", + "у", + "д", + "м", + "п", + "з", + "я", + "ь", + "б", + "г", + "й", + "ч", + "х", + "ц", + "ї", + ], + "Norwegian": [ + "e", + "r", + "n", + "t", + "a", + "s", + "i", + "o", + "l", + "d", + "g", + "k", + "m", + "v", + "f", + "p", + "u", + "b", + "h", + "å", + "y", + "j", + "ø", + "c", + "æ", + "w", + ], + "Finnish": [ + "a", + "i", + "n", + "t", + "e", + "s", + "l", + "o", + "u", + "k", + "ä", + "m", + "r", + "v", + "j", + "h", + "p", + "y", + "d", + "ö", + "g", + "c", + "b", + "f", + "w", + "z", + ], + "Vietnamese": [ + "n", + "h", + "t", + "i", + "c", + "g", + "a", + "o", + "u", + "m", + "l", + "r", + "à", + "đ", + "s", + "e", + "v", + "p", + "b", + "y", + "ư", + "d", + "á", + "k", + "ộ", + "ế", + ], + "Czech": [ + "o", + "e", + "a", + "n", + "t", + "s", + "i", + "l", + "v", + "r", + "k", + "d", + "u", + "m", + "p", + "í", + "c", + "h", + "z", + "á", + "y", + "j", + "b", + "ě", + "é", + "ř", + ], + "Hungarian": [ + "e", + "a", + "t", + "l", + "s", + "n", + "k", + "r", + "i", + "o", + "z", + "á", + "é", + "g", + "m", + "b", + "y", + "v", + "d", + "h", + "u", + "p", + "j", + "ö", + "f", + "c", + ], + "Korean": [ + "이", + "다", + "에", + "의", + "는", + "로", + "하", + "을", + "가", + "고", + "지", + "서", + "한", + "은", + "기", + "으", + "년", + "대", + "사", + "시", + "를", + "리", + "도", + "인", + "스", + "일", + ], + "Indonesian": [ + "a", + "n", + "e", + "i", + "r", + "t", + "u", + "s", + "d", + "k", + "m", + "l", + "g", + "p", + "b", + "o", + "h", + "y", + "j", + "c", + "w", + "f", + "v", + "z", + "x", + "q", + ], + "Turkish": [ + "a", + "e", + "i", + "n", + "r", + "l", + "ı", + "k", + "d", + "t", + "s", + "m", + "y", + "u", + "o", + "b", + "ü", + "ş", + "v", + "g", + "z", + "h", + "c", + "p", + "ç", + "ğ", + ], + "Romanian": [ + "e", + "i", + "a", + "r", + "n", + "t", + "u", + "l", + "o", + "c", + "s", + "d", + "p", + "m", + "ă", + "f", + "v", + "î", + "g", + "b", + "ș", + "ț", + "z", + "h", + "â", + "j", + ], + "Farsi": [ + "ا", + "ی", + "ر", + "د", + "ن", + "ه", + "و", + "م", + "ت", + "ب", + "س", + "ل", + "ک", + "ش", + "ز", + "ف", + "گ", + "ع", + "خ", + "ق", + "ج", + "آ", + "پ", + "ح", + "ط", + "ص", + ], + "Arabic": [ + "ا", + "ل", + "ي", + "م", + "و", + "ن", + "ر", + "ت", + "ب", + "ة", + "ع", + "د", + "س", + "ف", + "ه", + "ك", + "ق", + "أ", + "ح", + "ج", + "ش", + "ط", + "ص", + "ى", + "خ", + "إ", + ], + "Danish": [ + "e", + "r", + "n", + "t", + "a", + "i", + "s", + "d", + "l", + "o", + "g", + "m", + "k", + "f", + "v", + "u", + "b", + "h", + "p", + "å", + "y", + "ø", + "æ", + "c", + "j", + "w", + ], + "Serbian": [ + "а", + "и", + "о", + "е", + "н", + "р", + "с", + "у", + "т", + "к", + "ј", + "в", + "д", + "м", + "п", + "л", + "г", + "з", + "б", + "a", + "i", + "e", + "o", + "n", + "ц", + "ш", + ], + "Lithuanian": [ + "i", + "a", + "s", + "o", + "r", + "e", + "t", + "n", + "u", + "k", + "m", + "l", + "p", + "v", + "d", + "j", + "g", + "ė", + "b", + "y", + "ų", + "š", + "ž", + "c", + "ą", + "į", + ], + "Slovene": [ + "e", + "a", + "i", + "o", + "n", + "r", + "s", + "l", + "t", + "j", + "v", + "k", + "d", + "p", + "m", + "u", + "z", + "b", + "g", + "h", + "č", + "c", + "š", + "ž", + "f", + "y", + ], + "Slovak": [ + "o", + "a", + "e", + "n", + "i", + "r", + "v", + "t", + "s", + "l", + "k", + "d", + "m", + "p", + "u", + "c", + "h", + "j", + "b", + "z", + "á", + "y", + "ý", + "í", + "č", + "é", + ], + "Hebrew": [ + "י", + "ו", + "ה", + "ל", + "ר", + "ב", + "ת", + "מ", + "א", + "ש", + "נ", + "ע", + "ם", + "ד", + "ק", + "ח", + "פ", + "ס", + "כ", + "ג", + "ט", + "צ", + "ן", + "ז", + "ך", + ], + "Bulgarian": [ + "а", + "и", + "о", + "е", + "н", + "т", + "р", + "с", + "в", + "л", + "к", + "д", + "п", + "м", + "з", + "г", + "я", + "ъ", + "у", + "б", + "ч", + "ц", + "й", + "ж", + "щ", + "х", + ], + "Croatian": [ + "a", + "i", + "o", + "e", + "n", + "r", + "j", + "s", + "t", + "u", + "k", + "l", + "v", + "d", + "m", + "p", + "g", + "z", + "b", + "c", + "č", + "h", + "š", + "ž", + "ć", + "f", + ], + "Hindi": [ + "क", + "र", + "स", + "न", + "त", + "म", + "ह", + "प", + "य", + "ल", + "व", + "ज", + "द", + "ग", + "ब", + "श", + "ट", + "अ", + "ए", + "थ", + "भ", + "ड", + "च", + "ध", + "ष", + "इ", + ], + "Estonian": [ + "a", + "i", + "e", + "s", + "t", + "l", + "u", + "n", + "o", + "k", + "r", + "d", + "m", + "v", + "g", + "p", + "j", + "h", + "ä", + "b", + "õ", + "ü", + "f", + "c", + "ö", + "y", + ], + "Simple English": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "m", + "u", + "f", + "p", + "g", + "w", + "b", + "y", + "v", + "k", + "j", + "x", + "z", + "q", + ], + "Thai": [ + "า", + "น", + "ร", + "อ", + "ก", + "เ", + "ง", + "ม", + "ย", + "ล", + "ว", + "ด", + "ท", + "ส", + "ต", + "ะ", + "ป", + "บ", + "ค", + "ห", + "แ", + "จ", + "พ", + "ช", + "ข", + "ใ", + ], + "Greek": [ + "α", + "τ", + "ο", + "ι", + "ε", + "ν", + "ρ", + "σ", + "κ", + "η", + "π", + "ς", + "υ", + "μ", + "λ", + "ί", + "ό", + "ά", + "γ", + "έ", + "δ", + "ή", + "ω", + "χ", + "θ", + "ύ", + ], + "Tamil": [ + "க", + "த", + "ப", + "ட", + "ர", + "ம", + "ல", + "ன", + "வ", + "ற", + "ய", + "ள", + "ச", + "ந", + "இ", + "ண", + "அ", + "ஆ", + "ழ", + "ங", + "எ", + "உ", + "ஒ", + "ஸ", + ], + "Classical Chinese": [ + "之", + "年", + "為", + "也", + "以", + "一", + "人", + "其", + "者", + "國", + "有", + "二", + "十", + "於", + "曰", + "三", + "不", + "大", + "而", + "子", + "中", + "五", + "四", + ], + "Kazakh": [ + "а", + "ы", + "е", + "н", + "т", + "р", + "л", + "і", + "д", + "с", + "м", + "қ", + "к", + "о", + "б", + "и", + "у", + "ғ", + "ж", + "ң", + "з", + "ш", + "й", + "п", + "г", + "ө", + ], +} diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/cd.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/cd.py new file mode 100644 index 0000000..ee4b742 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/cd.py @@ -0,0 +1,339 @@ +import importlib +from codecs import IncrementalDecoder +from collections import Counter +from functools import lru_cache +from typing import Counter as TypeCounter, Dict, List, Optional, Tuple + +from .assets import FREQUENCIES +from .constant import KO_NAMES, LANGUAGE_SUPPORTED_COUNT, TOO_SMALL_SEQUENCE, ZH_NAMES +from .md import is_suspiciously_successive_range +from .models import CoherenceMatches +from .utils import ( + is_accentuated, + is_latin, + is_multi_byte_encoding, + is_unicode_range_secondary, + unicode_range, +) + + +def encoding_unicode_range(iana_name: str) -> List[str]: + """ + Return associated unicode ranges in a single byte code page. + """ + if is_multi_byte_encoding(iana_name): + raise IOError("Function not supported on multi-byte code page") + + decoder = importlib.import_module( + "encodings.{}".format(iana_name) + ).IncrementalDecoder + + p: IncrementalDecoder = decoder(errors="ignore") + seen_ranges: Dict[str, int] = {} + character_count: int = 0 + + for i in range(0x40, 0xFF): + chunk: str = p.decode(bytes([i])) + + if chunk: + character_range: Optional[str] = unicode_range(chunk) + + if character_range is None: + continue + + if is_unicode_range_secondary(character_range) is False: + if character_range not in seen_ranges: + seen_ranges[character_range] = 0 + seen_ranges[character_range] += 1 + character_count += 1 + + return sorted( + [ + character_range + for character_range in seen_ranges + if seen_ranges[character_range] / character_count >= 0.15 + ] + ) + + +def unicode_range_languages(primary_range: str) -> List[str]: + """ + Return inferred languages used with a unicode range. + """ + languages: List[str] = [] + + for language, characters in FREQUENCIES.items(): + for character in characters: + if unicode_range(character) == primary_range: + languages.append(language) + break + + return languages + + +@lru_cache() +def encoding_languages(iana_name: str) -> List[str]: + """ + Single-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + unicode_ranges: List[str] = encoding_unicode_range(iana_name) + primary_range: Optional[str] = None + + for specified_range in unicode_ranges: + if "Latin" not in specified_range: + primary_range = specified_range + break + + if primary_range is None: + return ["Latin Based"] + + return unicode_range_languages(primary_range) + + +@lru_cache() +def mb_encoding_languages(iana_name: str) -> List[str]: + """ + Multi-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + if ( + iana_name.startswith("shift_") + or iana_name.startswith("iso2022_jp") + or iana_name.startswith("euc_j") + or iana_name == "cp932" + ): + return ["Japanese"] + if iana_name.startswith("gb") or iana_name in ZH_NAMES: + return ["Chinese", "Classical Chinese"] + if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: + return ["Korean"] + + return [] + + +@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) +def get_target_features(language: str) -> Tuple[bool, bool]: + """ + Determine main aspects from a supported language if it contains accents and if is pure Latin. + """ + target_have_accents: bool = False + target_pure_latin: bool = True + + for character in FREQUENCIES[language]: + if not target_have_accents and is_accentuated(character): + target_have_accents = True + if target_pure_latin and is_latin(character) is False: + target_pure_latin = False + + return target_have_accents, target_pure_latin + + +def alphabet_languages( + characters: List[str], ignore_non_latin: bool = False +) -> List[str]: + """ + Return associated languages associated to given characters. + """ + languages: List[Tuple[str, float]] = [] + + source_have_accents = any(is_accentuated(character) for character in characters) + + for language, language_characters in FREQUENCIES.items(): + + target_have_accents, target_pure_latin = get_target_features(language) + + if ignore_non_latin and target_pure_latin is False: + continue + + if target_have_accents is False and source_have_accents: + continue + + character_count: int = len(language_characters) + + character_match_count: int = len( + [c for c in language_characters if c in characters] + ) + + ratio: float = character_match_count / character_count + + if ratio >= 0.2: + languages.append((language, ratio)) + + languages = sorted(languages, key=lambda x: x[1], reverse=True) + + return [compatible_language[0] for compatible_language in languages] + + +def characters_popularity_compare( + language: str, ordered_characters: List[str] +) -> float: + """ + Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. + The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). + Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) + """ + if language not in FREQUENCIES: + raise ValueError("{} not available".format(language)) + + character_approved_count: int = 0 + FREQUENCIES_language_set = set(FREQUENCIES[language]) + + for character in ordered_characters: + if character not in FREQUENCIES_language_set: + continue + + characters_before_source: List[str] = FREQUENCIES[language][ + 0 : FREQUENCIES[language].index(character) + ] + characters_after_source: List[str] = FREQUENCIES[language][ + FREQUENCIES[language].index(character) : + ] + characters_before: List[str] = ordered_characters[ + 0 : ordered_characters.index(character) + ] + characters_after: List[str] = ordered_characters[ + ordered_characters.index(character) : + ] + + before_match_count: int = len( + set(characters_before) & set(characters_before_source) + ) + + after_match_count: int = len( + set(characters_after) & set(characters_after_source) + ) + + if len(characters_before_source) == 0 and before_match_count <= 4: + character_approved_count += 1 + continue + + if len(characters_after_source) == 0 and after_match_count <= 4: + character_approved_count += 1 + continue + + if ( + before_match_count / len(characters_before_source) >= 0.4 + or after_match_count / len(characters_after_source) >= 0.4 + ): + character_approved_count += 1 + continue + + return character_approved_count / len(ordered_characters) + + +def alpha_unicode_split(decoded_sequence: str) -> List[str]: + """ + Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. + Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; + One containing the latin letters and the other hebrew. + """ + layers: Dict[str, str] = {} + + for character in decoded_sequence: + if character.isalpha() is False: + continue + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + continue + + layer_target_range: Optional[str] = None + + for discovered_range in layers: + if ( + is_suspiciously_successive_range(discovered_range, character_range) + is False + ): + layer_target_range = discovered_range + break + + if layer_target_range is None: + layer_target_range = character_range + + if layer_target_range not in layers: + layers[layer_target_range] = character.lower() + continue + + layers[layer_target_range] += character.lower() + + return list(layers.values()) + + +def merge_coherence_ratios(results: List[CoherenceMatches]) -> CoherenceMatches: + """ + This function merge results previously given by the function coherence_ratio. + The return type is the same as coherence_ratio. + """ + per_language_ratios: Dict[str, List[float]] = {} + for result in results: + for sub_result in result: + language, ratio = sub_result + if language not in per_language_ratios: + per_language_ratios[language] = [ratio] + continue + per_language_ratios[language].append(ratio) + + merge = [ + ( + language, + round( + sum(per_language_ratios[language]) / len(per_language_ratios[language]), + 4, + ), + ) + for language in per_language_ratios + ] + + return sorted(merge, key=lambda x: x[1], reverse=True) + + +@lru_cache(maxsize=2048) +def coherence_ratio( + decoded_sequence: str, threshold: float = 0.1, lg_inclusion: Optional[str] = None +) -> CoherenceMatches: + """ + Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. + A layer = Character extraction by alphabets/ranges. + """ + + results: List[Tuple[str, float]] = [] + ignore_non_latin: bool = False + + sufficient_match_count: int = 0 + + lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] + if "Latin Based" in lg_inclusion_list: + ignore_non_latin = True + lg_inclusion_list.remove("Latin Based") + + for layer in alpha_unicode_split(decoded_sequence): + sequence_frequencies: TypeCounter[str] = Counter(layer) + most_common = sequence_frequencies.most_common() + + character_count: int = sum(o for c, o in most_common) + + if character_count <= TOO_SMALL_SEQUENCE: + continue + + popular_character_ordered: List[str] = [c for c, o in most_common] + + for language in lg_inclusion_list or alphabet_languages( + popular_character_ordered, ignore_non_latin + ): + ratio: float = characters_popularity_compare( + language, popular_character_ordered + ) + + if ratio < threshold: + continue + elif ratio >= 0.8: + sufficient_match_count += 1 + + results.append((language, round(ratio, 4))) + + if sufficient_match_count >= 3: + break + + return sorted(results, key=lambda x: x[1], reverse=True) diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/cli/__init__.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/cli/normalizer.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/cli/normalizer.py new file mode 100644 index 0000000..b8b652a --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/cli/normalizer.py @@ -0,0 +1,295 @@ +import argparse +import sys +from json import dumps +from os.path import abspath +from platform import python_version +from typing import List, Optional + +try: + from unicodedata2 import unidata_version +except ImportError: + from unicodedata import unidata_version + +from charset_normalizer import from_fp +from charset_normalizer.models import CliDetectionResult +from charset_normalizer.version import __version__ + + +def query_yes_no(question: str, default: str = "yes") -> bool: + """Ask a yes/no question via input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits . + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is True for "yes" or False for "no". + + Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input + """ + valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} + if default is None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while True: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == "": + return valid[default] + elif choice in valid: + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n") + + +def cli_detect(argv: Optional[List[str]] = None) -> int: + """ + CLI assistant using ARGV and ArgumentParser + :param argv: + :return: 0 if everything is fine, anything else equal trouble + """ + parser = argparse.ArgumentParser( + description="The Real First Universal Charset Detector. " + "Discover originating encoding used on text file. " + "Normalize text to unicode." + ) + + parser.add_argument( + "files", type=argparse.FileType("rb"), nargs="+", help="File(s) to be analysed" + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + default=False, + dest="verbose", + help="Display complementary information about file if any. " + "Stdout will contain logs about the detection process.", + ) + parser.add_argument( + "-a", + "--with-alternative", + action="store_true", + default=False, + dest="alternatives", + help="Output complementary possibilities if any. Top-level JSON WILL be a list.", + ) + parser.add_argument( + "-n", + "--normalize", + action="store_true", + default=False, + dest="normalize", + help="Permit to normalize input file. If not set, program does not write anything.", + ) + parser.add_argument( + "-m", + "--minimal", + action="store_true", + default=False, + dest="minimal", + help="Only output the charset detected to STDOUT. Disabling JSON output.", + ) + parser.add_argument( + "-r", + "--replace", + action="store_true", + default=False, + dest="replace", + help="Replace file when trying to normalize it instead of creating a new one.", + ) + parser.add_argument( + "-f", + "--force", + action="store_true", + default=False, + dest="force", + help="Replace file without asking if you are sure, use this flag with caution.", + ) + parser.add_argument( + "-t", + "--threshold", + action="store", + default=0.2, + type=float, + dest="threshold", + help="Define a custom maximum amount of chaos allowed in decoded content. 0. <= chaos <= 1.", + ) + parser.add_argument( + "--version", + action="version", + version="Charset-Normalizer {} - Python {} - Unicode {}".format( + __version__, python_version(), unidata_version + ), + help="Show version information and exit.", + ) + + args = parser.parse_args(argv) + + if args.replace is True and args.normalize is False: + print("Use --replace in addition of --normalize only.", file=sys.stderr) + return 1 + + if args.force is True and args.replace is False: + print("Use --force in addition of --replace only.", file=sys.stderr) + return 1 + + if args.threshold < 0.0 or args.threshold > 1.0: + print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) + return 1 + + x_ = [] + + for my_file in args.files: + + matches = from_fp(my_file, threshold=args.threshold, explain=args.verbose) + + best_guess = matches.best() + + if best_guess is None: + print( + 'Unable to identify originating encoding for "{}". {}'.format( + my_file.name, + "Maybe try increasing maximum amount of chaos." + if args.threshold < 1.0 + else "", + ), + file=sys.stderr, + ) + x_.append( + CliDetectionResult( + abspath(my_file.name), + None, + [], + [], + "Unknown", + [], + False, + 1.0, + 0.0, + None, + True, + ) + ) + else: + x_.append( + CliDetectionResult( + abspath(my_file.name), + best_guess.encoding, + best_guess.encoding_aliases, + [ + cp + for cp in best_guess.could_be_from_charset + if cp != best_guess.encoding + ], + best_guess.language, + best_guess.alphabets, + best_guess.bom, + best_guess.percent_chaos, + best_guess.percent_coherence, + None, + True, + ) + ) + + if len(matches) > 1 and args.alternatives: + for el in matches: + if el != best_guess: + x_.append( + CliDetectionResult( + abspath(my_file.name), + el.encoding, + el.encoding_aliases, + [ + cp + for cp in el.could_be_from_charset + if cp != el.encoding + ], + el.language, + el.alphabets, + el.bom, + el.percent_chaos, + el.percent_coherence, + None, + False, + ) + ) + + if args.normalize is True: + + if best_guess.encoding.startswith("utf") is True: + print( + '"{}" file does not need to be normalized, as it already came from unicode.'.format( + my_file.name + ), + file=sys.stderr, + ) + if my_file.closed is False: + my_file.close() + continue + + o_: List[str] = my_file.name.split(".") + + if args.replace is False: + o_.insert(-1, best_guess.encoding) + if my_file.closed is False: + my_file.close() + elif ( + args.force is False + and query_yes_no( + 'Are you sure to normalize "{}" by replacing it ?'.format( + my_file.name + ), + "no", + ) + is False + ): + if my_file.closed is False: + my_file.close() + continue + + try: + x_[0].unicode_path = abspath("./{}".format(".".join(o_))) + + with open(x_[0].unicode_path, "w", encoding="utf-8") as fp: + fp.write(str(best_guess)) + except IOError as e: + print(str(e), file=sys.stderr) + if my_file.closed is False: + my_file.close() + return 2 + + if my_file.closed is False: + my_file.close() + + if args.minimal is False: + print( + dumps( + [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, + ensure_ascii=True, + indent=4, + ) + ) + else: + for my_file in args.files: + print( + ", ".join( + [ + el.encoding or "undefined" + for el in x_ + if el.path == abspath(my_file.name) + ] + ) + ) + + return 0 + + +if __name__ == "__main__": + cli_detect() diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/constant.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/constant.py new file mode 100644 index 0000000..ac840c4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/constant.py @@ -0,0 +1,497 @@ +from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE +from encodings.aliases import aliases +from re import IGNORECASE, compile as re_compile +from typing import Dict, List, Set, Union + +from .assets import FREQUENCIES + +# Contain for each eligible encoding a list of/item bytes SIG/BOM +ENCODING_MARKS: Dict[str, Union[bytes, List[bytes]]] = { + "utf_8": BOM_UTF8, + "utf_7": [ + b"\x2b\x2f\x76\x38", + b"\x2b\x2f\x76\x39", + b"\x2b\x2f\x76\x2b", + b"\x2b\x2f\x76\x2f", + b"\x2b\x2f\x76\x38\x2d", + ], + "gb18030": b"\x84\x31\x95\x33", + "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], + "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], +} + +TOO_SMALL_SEQUENCE: int = 32 +TOO_BIG_SEQUENCE: int = int(10e6) + +UTF8_MAXIMAL_ALLOCATION: int = 1112064 + +UNICODE_RANGES_COMBINED: Dict[str, range] = { + "Control character": range(31 + 1), + "Basic Latin": range(32, 127 + 1), + "Latin-1 Supplement": range(128, 255 + 1), + "Latin Extended-A": range(256, 383 + 1), + "Latin Extended-B": range(384, 591 + 1), + "IPA Extensions": range(592, 687 + 1), + "Spacing Modifier Letters": range(688, 767 + 1), + "Combining Diacritical Marks": range(768, 879 + 1), + "Greek and Coptic": range(880, 1023 + 1), + "Cyrillic": range(1024, 1279 + 1), + "Cyrillic Supplement": range(1280, 1327 + 1), + "Armenian": range(1328, 1423 + 1), + "Hebrew": range(1424, 1535 + 1), + "Arabic": range(1536, 1791 + 1), + "Syriac": range(1792, 1871 + 1), + "Arabic Supplement": range(1872, 1919 + 1), + "Thaana": range(1920, 1983 + 1), + "NKo": range(1984, 2047 + 1), + "Samaritan": range(2048, 2111 + 1), + "Mandaic": range(2112, 2143 + 1), + "Syriac Supplement": range(2144, 2159 + 1), + "Arabic Extended-A": range(2208, 2303 + 1), + "Devanagari": range(2304, 2431 + 1), + "Bengali": range(2432, 2559 + 1), + "Gurmukhi": range(2560, 2687 + 1), + "Gujarati": range(2688, 2815 + 1), + "Oriya": range(2816, 2943 + 1), + "Tamil": range(2944, 3071 + 1), + "Telugu": range(3072, 3199 + 1), + "Kannada": range(3200, 3327 + 1), + "Malayalam": range(3328, 3455 + 1), + "Sinhala": range(3456, 3583 + 1), + "Thai": range(3584, 3711 + 1), + "Lao": range(3712, 3839 + 1), + "Tibetan": range(3840, 4095 + 1), + "Myanmar": range(4096, 4255 + 1), + "Georgian": range(4256, 4351 + 1), + "Hangul Jamo": range(4352, 4607 + 1), + "Ethiopic": range(4608, 4991 + 1), + "Ethiopic Supplement": range(4992, 5023 + 1), + "Cherokee": range(5024, 5119 + 1), + "Unified Canadian Aboriginal Syllabics": range(5120, 5759 + 1), + "Ogham": range(5760, 5791 + 1), + "Runic": range(5792, 5887 + 1), + "Tagalog": range(5888, 5919 + 1), + "Hanunoo": range(5920, 5951 + 1), + "Buhid": range(5952, 5983 + 1), + "Tagbanwa": range(5984, 6015 + 1), + "Khmer": range(6016, 6143 + 1), + "Mongolian": range(6144, 6319 + 1), + "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6399 + 1), + "Limbu": range(6400, 6479 + 1), + "Tai Le": range(6480, 6527 + 1), + "New Tai Lue": range(6528, 6623 + 1), + "Khmer Symbols": range(6624, 6655 + 1), + "Buginese": range(6656, 6687 + 1), + "Tai Tham": range(6688, 6831 + 1), + "Combining Diacritical Marks Extended": range(6832, 6911 + 1), + "Balinese": range(6912, 7039 + 1), + "Sundanese": range(7040, 7103 + 1), + "Batak": range(7104, 7167 + 1), + "Lepcha": range(7168, 7247 + 1), + "Ol Chiki": range(7248, 7295 + 1), + "Cyrillic Extended C": range(7296, 7311 + 1), + "Sundanese Supplement": range(7360, 7375 + 1), + "Vedic Extensions": range(7376, 7423 + 1), + "Phonetic Extensions": range(7424, 7551 + 1), + "Phonetic Extensions Supplement": range(7552, 7615 + 1), + "Combining Diacritical Marks Supplement": range(7616, 7679 + 1), + "Latin Extended Additional": range(7680, 7935 + 1), + "Greek Extended": range(7936, 8191 + 1), + "General Punctuation": range(8192, 8303 + 1), + "Superscripts and Subscripts": range(8304, 8351 + 1), + "Currency Symbols": range(8352, 8399 + 1), + "Combining Diacritical Marks for Symbols": range(8400, 8447 + 1), + "Letterlike Symbols": range(8448, 8527 + 1), + "Number Forms": range(8528, 8591 + 1), + "Arrows": range(8592, 8703 + 1), + "Mathematical Operators": range(8704, 8959 + 1), + "Miscellaneous Technical": range(8960, 9215 + 1), + "Control Pictures": range(9216, 9279 + 1), + "Optical Character Recognition": range(9280, 9311 + 1), + "Enclosed Alphanumerics": range(9312, 9471 + 1), + "Box Drawing": range(9472, 9599 + 1), + "Block Elements": range(9600, 9631 + 1), + "Geometric Shapes": range(9632, 9727 + 1), + "Miscellaneous Symbols": range(9728, 9983 + 1), + "Dingbats": range(9984, 10175 + 1), + "Miscellaneous Mathematical Symbols-A": range(10176, 10223 + 1), + "Supplemental Arrows-A": range(10224, 10239 + 1), + "Braille Patterns": range(10240, 10495 + 1), + "Supplemental Arrows-B": range(10496, 10623 + 1), + "Miscellaneous Mathematical Symbols-B": range(10624, 10751 + 1), + "Supplemental Mathematical Operators": range(10752, 11007 + 1), + "Miscellaneous Symbols and Arrows": range(11008, 11263 + 1), + "Glagolitic": range(11264, 11359 + 1), + "Latin Extended-C": range(11360, 11391 + 1), + "Coptic": range(11392, 11519 + 1), + "Georgian Supplement": range(11520, 11567 + 1), + "Tifinagh": range(11568, 11647 + 1), + "Ethiopic Extended": range(11648, 11743 + 1), + "Cyrillic Extended-A": range(11744, 11775 + 1), + "Supplemental Punctuation": range(11776, 11903 + 1), + "CJK Radicals Supplement": range(11904, 12031 + 1), + "Kangxi Radicals": range(12032, 12255 + 1), + "Ideographic Description Characters": range(12272, 12287 + 1), + "CJK Symbols and Punctuation": range(12288, 12351 + 1), + "Hiragana": range(12352, 12447 + 1), + "Katakana": range(12448, 12543 + 1), + "Bopomofo": range(12544, 12591 + 1), + "Hangul Compatibility Jamo": range(12592, 12687 + 1), + "Kanbun": range(12688, 12703 + 1), + "Bopomofo Extended": range(12704, 12735 + 1), + "CJK Strokes": range(12736, 12783 + 1), + "Katakana Phonetic Extensions": range(12784, 12799 + 1), + "Enclosed CJK Letters and Months": range(12800, 13055 + 1), + "CJK Compatibility": range(13056, 13311 + 1), + "CJK Unified Ideographs Extension A": range(13312, 19903 + 1), + "Yijing Hexagram Symbols": range(19904, 19967 + 1), + "CJK Unified Ideographs": range(19968, 40959 + 1), + "Yi Syllables": range(40960, 42127 + 1), + "Yi Radicals": range(42128, 42191 + 1), + "Lisu": range(42192, 42239 + 1), + "Vai": range(42240, 42559 + 1), + "Cyrillic Extended-B": range(42560, 42655 + 1), + "Bamum": range(42656, 42751 + 1), + "Modifier Tone Letters": range(42752, 42783 + 1), + "Latin Extended-D": range(42784, 43007 + 1), + "Syloti Nagri": range(43008, 43055 + 1), + "Common Indic Number Forms": range(43056, 43071 + 1), + "Phags-pa": range(43072, 43135 + 1), + "Saurashtra": range(43136, 43231 + 1), + "Devanagari Extended": range(43232, 43263 + 1), + "Kayah Li": range(43264, 43311 + 1), + "Rejang": range(43312, 43359 + 1), + "Hangul Jamo Extended-A": range(43360, 43391 + 1), + "Javanese": range(43392, 43487 + 1), + "Myanmar Extended-B": range(43488, 43519 + 1), + "Cham": range(43520, 43615 + 1), + "Myanmar Extended-A": range(43616, 43647 + 1), + "Tai Viet": range(43648, 43743 + 1), + "Meetei Mayek Extensions": range(43744, 43775 + 1), + "Ethiopic Extended-A": range(43776, 43823 + 1), + "Latin Extended-E": range(43824, 43887 + 1), + "Cherokee Supplement": range(43888, 43967 + 1), + "Meetei Mayek": range(43968, 44031 + 1), + "Hangul Syllables": range(44032, 55215 + 1), + "Hangul Jamo Extended-B": range(55216, 55295 + 1), + "High Surrogates": range(55296, 56191 + 1), + "High Private Use Surrogates": range(56192, 56319 + 1), + "Low Surrogates": range(56320, 57343 + 1), + "Private Use Area": range(57344, 63743 + 1), + "CJK Compatibility Ideographs": range(63744, 64255 + 1), + "Alphabetic Presentation Forms": range(64256, 64335 + 1), + "Arabic Presentation Forms-A": range(64336, 65023 + 1), + "Variation Selectors": range(65024, 65039 + 1), + "Vertical Forms": range(65040, 65055 + 1), + "Combining Half Marks": range(65056, 65071 + 1), + "CJK Compatibility Forms": range(65072, 65103 + 1), + "Small Form Variants": range(65104, 65135 + 1), + "Arabic Presentation Forms-B": range(65136, 65279 + 1), + "Halfwidth and Fullwidth Forms": range(65280, 65519 + 1), + "Specials": range(65520, 65535 + 1), + "Linear B Syllabary": range(65536, 65663 + 1), + "Linear B Ideograms": range(65664, 65791 + 1), + "Aegean Numbers": range(65792, 65855 + 1), + "Ancient Greek Numbers": range(65856, 65935 + 1), + "Ancient Symbols": range(65936, 65999 + 1), + "Phaistos Disc": range(66000, 66047 + 1), + "Lycian": range(66176, 66207 + 1), + "Carian": range(66208, 66271 + 1), + "Coptic Epact Numbers": range(66272, 66303 + 1), + "Old Italic": range(66304, 66351 + 1), + "Gothic": range(66352, 66383 + 1), + "Old Permic": range(66384, 66431 + 1), + "Ugaritic": range(66432, 66463 + 1), + "Old Persian": range(66464, 66527 + 1), + "Deseret": range(66560, 66639 + 1), + "Shavian": range(66640, 66687 + 1), + "Osmanya": range(66688, 66735 + 1), + "Osage": range(66736, 66815 + 1), + "Elbasan": range(66816, 66863 + 1), + "Caucasian Albanian": range(66864, 66927 + 1), + "Linear A": range(67072, 67455 + 1), + "Cypriot Syllabary": range(67584, 67647 + 1), + "Imperial Aramaic": range(67648, 67679 + 1), + "Palmyrene": range(67680, 67711 + 1), + "Nabataean": range(67712, 67759 + 1), + "Hatran": range(67808, 67839 + 1), + "Phoenician": range(67840, 67871 + 1), + "Lydian": range(67872, 67903 + 1), + "Meroitic Hieroglyphs": range(67968, 67999 + 1), + "Meroitic Cursive": range(68000, 68095 + 1), + "Kharoshthi": range(68096, 68191 + 1), + "Old South Arabian": range(68192, 68223 + 1), + "Old North Arabian": range(68224, 68255 + 1), + "Manichaean": range(68288, 68351 + 1), + "Avestan": range(68352, 68415 + 1), + "Inscriptional Parthian": range(68416, 68447 + 1), + "Inscriptional Pahlavi": range(68448, 68479 + 1), + "Psalter Pahlavi": range(68480, 68527 + 1), + "Old Turkic": range(68608, 68687 + 1), + "Old Hungarian": range(68736, 68863 + 1), + "Rumi Numeral Symbols": range(69216, 69247 + 1), + "Brahmi": range(69632, 69759 + 1), + "Kaithi": range(69760, 69839 + 1), + "Sora Sompeng": range(69840, 69887 + 1), + "Chakma": range(69888, 69967 + 1), + "Mahajani": range(69968, 70015 + 1), + "Sharada": range(70016, 70111 + 1), + "Sinhala Archaic Numbers": range(70112, 70143 + 1), + "Khojki": range(70144, 70223 + 1), + "Multani": range(70272, 70319 + 1), + "Khudawadi": range(70320, 70399 + 1), + "Grantha": range(70400, 70527 + 1), + "Newa": range(70656, 70783 + 1), + "Tirhuta": range(70784, 70879 + 1), + "Siddham": range(71040, 71167 + 1), + "Modi": range(71168, 71263 + 1), + "Mongolian Supplement": range(71264, 71295 + 1), + "Takri": range(71296, 71375 + 1), + "Ahom": range(71424, 71487 + 1), + "Warang Citi": range(71840, 71935 + 1), + "Zanabazar Square": range(72192, 72271 + 1), + "Soyombo": range(72272, 72367 + 1), + "Pau Cin Hau": range(72384, 72447 + 1), + "Bhaiksuki": range(72704, 72815 + 1), + "Marchen": range(72816, 72895 + 1), + "Masaram Gondi": range(72960, 73055 + 1), + "Cuneiform": range(73728, 74751 + 1), + "Cuneiform Numbers and Punctuation": range(74752, 74879 + 1), + "Early Dynastic Cuneiform": range(74880, 75087 + 1), + "Egyptian Hieroglyphs": range(77824, 78895 + 1), + "Anatolian Hieroglyphs": range(82944, 83583 + 1), + "Bamum Supplement": range(92160, 92735 + 1), + "Mro": range(92736, 92783 + 1), + "Bassa Vah": range(92880, 92927 + 1), + "Pahawh Hmong": range(92928, 93071 + 1), + "Miao": range(93952, 94111 + 1), + "Ideographic Symbols and Punctuation": range(94176, 94207 + 1), + "Tangut": range(94208, 100351 + 1), + "Tangut Components": range(100352, 101119 + 1), + "Kana Supplement": range(110592, 110847 + 1), + "Kana Extended-A": range(110848, 110895 + 1), + "Nushu": range(110960, 111359 + 1), + "Duployan": range(113664, 113823 + 1), + "Shorthand Format Controls": range(113824, 113839 + 1), + "Byzantine Musical Symbols": range(118784, 119039 + 1), + "Musical Symbols": range(119040, 119295 + 1), + "Ancient Greek Musical Notation": range(119296, 119375 + 1), + "Tai Xuan Jing Symbols": range(119552, 119647 + 1), + "Counting Rod Numerals": range(119648, 119679 + 1), + "Mathematical Alphanumeric Symbols": range(119808, 120831 + 1), + "Sutton SignWriting": range(120832, 121519 + 1), + "Glagolitic Supplement": range(122880, 122927 + 1), + "Mende Kikakui": range(124928, 125151 + 1), + "Adlam": range(125184, 125279 + 1), + "Arabic Mathematical Alphabetic Symbols": range(126464, 126719 + 1), + "Mahjong Tiles": range(126976, 127023 + 1), + "Domino Tiles": range(127024, 127135 + 1), + "Playing Cards": range(127136, 127231 + 1), + "Enclosed Alphanumeric Supplement": range(127232, 127487 + 1), + "Enclosed Ideographic Supplement": range(127488, 127743 + 1), + "Miscellaneous Symbols and Pictographs": range(127744, 128511 + 1), + "Emoticons range(Emoji)": range(128512, 128591 + 1), + "Ornamental Dingbats": range(128592, 128639 + 1), + "Transport and Map Symbols": range(128640, 128767 + 1), + "Alchemical Symbols": range(128768, 128895 + 1), + "Geometric Shapes Extended": range(128896, 129023 + 1), + "Supplemental Arrows-C": range(129024, 129279 + 1), + "Supplemental Symbols and Pictographs": range(129280, 129535 + 1), + "CJK Unified Ideographs Extension B": range(131072, 173791 + 1), + "CJK Unified Ideographs Extension C": range(173824, 177983 + 1), + "CJK Unified Ideographs Extension D": range(177984, 178207 + 1), + "CJK Unified Ideographs Extension E": range(178208, 183983 + 1), + "CJK Unified Ideographs Extension F": range(183984, 191471 + 1), + "CJK Compatibility Ideographs Supplement": range(194560, 195103 + 1), + "Tags": range(917504, 917631 + 1), + "Variation Selectors Supplement": range(917760, 917999 + 1), +} + + +UNICODE_SECONDARY_RANGE_KEYWORD: List[str] = [ + "Supplement", + "Extended", + "Extensions", + "Modifier", + "Marks", + "Punctuation", + "Symbols", + "Forms", + "Operators", + "Miscellaneous", + "Drawing", + "Block", + "Shapes", + "Supplemental", + "Tags", +] + +RE_POSSIBLE_ENCODING_INDICATION = re_compile( + r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", + IGNORECASE, +) + +IANA_SUPPORTED: List[str] = sorted( + filter( + lambda x: x.endswith("_codec") is False + and x not in {"rot_13", "tactis", "mbcs"}, + list(set(aliases.values())), + ) +) + +IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) + +# pre-computed code page that are similar using the function cp_similarity. +IANA_SUPPORTED_SIMILAR: Dict[str, List[str]] = { + "cp037": ["cp1026", "cp1140", "cp273", "cp500"], + "cp1026": ["cp037", "cp1140", "cp273", "cp500"], + "cp1125": ["cp866"], + "cp1140": ["cp037", "cp1026", "cp273", "cp500"], + "cp1250": ["iso8859_2"], + "cp1251": ["kz1048", "ptcp154"], + "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1253": ["iso8859_7"], + "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1257": ["iso8859_13"], + "cp273": ["cp037", "cp1026", "cp1140", "cp500"], + "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], + "cp500": ["cp037", "cp1026", "cp1140", "cp273"], + "cp850": ["cp437", "cp857", "cp858", "cp865"], + "cp857": ["cp850", "cp858", "cp865"], + "cp858": ["cp437", "cp850", "cp857", "cp865"], + "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], + "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], + "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], + "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], + "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], + "cp866": ["cp1125"], + "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], + "iso8859_11": ["tis_620"], + "iso8859_13": ["cp1257"], + "iso8859_14": [ + "iso8859_10", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_15": [ + "cp1252", + "cp1254", + "iso8859_10", + "iso8859_14", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_16": [ + "iso8859_14", + "iso8859_15", + "iso8859_2", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], + "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], + "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], + "iso8859_7": ["cp1253"], + "iso8859_9": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "latin_1", + ], + "kz1048": ["cp1251", "ptcp154"], + "latin_1": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "iso8859_9", + ], + "mac_iceland": ["mac_roman", "mac_turkish"], + "mac_roman": ["mac_iceland", "mac_turkish"], + "mac_turkish": ["mac_iceland", "mac_roman"], + "ptcp154": ["cp1251", "kz1048"], + "tis_620": ["iso8859_11"], +} + + +CHARDET_CORRESPONDENCE: Dict[str, str] = { + "iso2022_kr": "ISO-2022-KR", + "iso2022_jp": "ISO-2022-JP", + "euc_kr": "EUC-KR", + "tis_620": "TIS-620", + "utf_32": "UTF-32", + "euc_jp": "EUC-JP", + "koi8_r": "KOI8-R", + "iso8859_1": "ISO-8859-1", + "iso8859_2": "ISO-8859-2", + "iso8859_5": "ISO-8859-5", + "iso8859_6": "ISO-8859-6", + "iso8859_7": "ISO-8859-7", + "iso8859_8": "ISO-8859-8", + "utf_16": "UTF-16", + "cp855": "IBM855", + "mac_cyrillic": "MacCyrillic", + "gb2312": "GB2312", + "gb18030": "GB18030", + "cp932": "CP932", + "cp866": "IBM866", + "utf_8": "utf-8", + "utf_8_sig": "UTF-8-SIG", + "shift_jis": "SHIFT_JIS", + "big5": "Big5", + "cp1250": "windows-1250", + "cp1251": "windows-1251", + "cp1252": "Windows-1252", + "cp1253": "windows-1253", + "cp1255": "windows-1255", + "cp1256": "windows-1256", + "cp1254": "Windows-1254", + "cp949": "CP949", +} + + +COMMON_SAFE_ASCII_CHARACTERS: Set[str] = { + "<", + ">", + "=", + ":", + "/", + "&", + ";", + "{", + "}", + "[", + "]", + ",", + "|", + '"', + "-", +} + + +KO_NAMES: Set[str] = {"johab", "cp949", "euc_kr"} +ZH_NAMES: Set[str] = {"big5", "cp950", "big5hkscs", "hz"} + +NOT_PRINTABLE_PATTERN = re_compile(r"[0-9\W\n\r\t]+") + +LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) + +# Logging LEVEL bellow DEBUG +TRACE: int = 5 diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/legacy.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/legacy.py new file mode 100644 index 0000000..cdebe2b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/legacy.py @@ -0,0 +1,95 @@ +import warnings +from typing import Dict, Optional, Union + +from .api import from_bytes, from_fp, from_path, normalize +from .constant import CHARDET_CORRESPONDENCE +from .models import CharsetMatch, CharsetMatches + + +def detect(byte_str: bytes) -> Dict[str, Optional[Union[str, float]]]: + """ + chardet legacy method + Detect the encoding of the given byte string. It should be mostly backward-compatible. + Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) + This function is deprecated and should be used to migrate your project easily, consult the documentation for + further information. Not planned for removal. + + :param byte_str: The byte sequence to examine. + """ + if not isinstance(byte_str, (bytearray, bytes)): + raise TypeError( # pragma: nocover + "Expected object of type bytes or bytearray, got: " + "{0}".format(type(byte_str)) + ) + + if isinstance(byte_str, bytearray): + byte_str = bytes(byte_str) + + r = from_bytes(byte_str).best() + + encoding = r.encoding if r is not None else None + language = r.language if r is not None and r.language != "Unknown" else "" + confidence = 1.0 - r.chaos if r is not None else None + + # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process + # but chardet does return 'utf-8-sig' and it is a valid codec name. + if r is not None and encoding == "utf_8" and r.bom: + encoding += "_sig" + + return { + "encoding": encoding + if encoding not in CHARDET_CORRESPONDENCE + else CHARDET_CORRESPONDENCE[encoding], + "language": language, + "confidence": confidence, + } + + +class CharsetNormalizerMatch(CharsetMatch): + pass + + +class CharsetNormalizerMatches(CharsetMatches): + @staticmethod + def from_fp(*args, **kwargs): # type: ignore + warnings.warn( # pragma: nocover + "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " + "and scheduled to be removed in 3.0", + DeprecationWarning, + ) + return from_fp(*args, **kwargs) # pragma: nocover + + @staticmethod + def from_bytes(*args, **kwargs): # type: ignore + warnings.warn( # pragma: nocover + "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " + "and scheduled to be removed in 3.0", + DeprecationWarning, + ) + return from_bytes(*args, **kwargs) # pragma: nocover + + @staticmethod + def from_path(*args, **kwargs): # type: ignore + warnings.warn( # pragma: nocover + "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " + "and scheduled to be removed in 3.0", + DeprecationWarning, + ) + return from_path(*args, **kwargs) # pragma: nocover + + @staticmethod + def normalize(*args, **kwargs): # type: ignore + warnings.warn( # pragma: nocover + "staticmethod from_fp, from_bytes, from_path and normalize are deprecated " + "and scheduled to be removed in 3.0", + DeprecationWarning, + ) + return normalize(*args, **kwargs) # pragma: nocover + + +class CharsetDetector(CharsetNormalizerMatches): + pass + + +class CharsetDoctor(CharsetNormalizerMatches): + pass diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/md.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/md.py new file mode 100644 index 0000000..31808af --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/md.py @@ -0,0 +1,553 @@ +from functools import lru_cache +from typing import List, Optional + +from .constant import COMMON_SAFE_ASCII_CHARACTERS, UNICODE_SECONDARY_RANGE_KEYWORD +from .utils import ( + is_accentuated, + is_ascii, + is_case_variable, + is_cjk, + is_emoticon, + is_hangul, + is_hiragana, + is_katakana, + is_latin, + is_punctuation, + is_separator, + is_symbol, + is_thai, + is_unprintable, + remove_accent, + unicode_range, +) + + +class MessDetectorPlugin: + """ + Base abstract class used for mess detection plugins. + All detectors MUST extend and implement given methods. + """ + + def eligible(self, character: str) -> bool: + """ + Determine if given character should be fed in. + """ + raise NotImplementedError # pragma: nocover + + def feed(self, character: str) -> None: + """ + The main routine to be executed upon character. + Insert the logic in witch the text would be considered chaotic. + """ + raise NotImplementedError # pragma: nocover + + def reset(self) -> None: # pragma: no cover + """ + Permit to reset the plugin to the initial state. + """ + raise NotImplementedError + + @property + def ratio(self) -> float: + """ + Compute the chaos ratio based on what your feed() has seen. + Must NOT be lower than 0.; No restriction gt 0. + """ + raise NotImplementedError # pragma: nocover + + +class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._punctuation_count: int = 0 + self._symbol_count: int = 0 + self._character_count: int = 0 + + self._last_printable_char: Optional[str] = None + self._frenzy_symbol_in_word: bool = False + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character != self._last_printable_char + and character not in COMMON_SAFE_ASCII_CHARACTERS + ): + if is_punctuation(character): + self._punctuation_count += 1 + elif ( + character.isdigit() is False + and is_symbol(character) + and is_emoticon(character) is False + ): + self._symbol_count += 2 + + self._last_printable_char = character + + def reset(self) -> None: # pragma: no cover + self._punctuation_count = 0 + self._character_count = 0 + self._symbol_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + ratio_of_punctuation: float = ( + self._punctuation_count + self._symbol_count + ) / self._character_count + + return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 + + +class TooManyAccentuatedPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._character_count: int = 0 + self._accentuated_count: int = 0 + + def eligible(self, character: str) -> bool: + return character.isalpha() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_accentuated(character): + self._accentuated_count += 1 + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._accentuated_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + ratio_of_accentuation: float = self._accentuated_count / self._character_count + return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 + + +class UnprintablePlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._unprintable_count: int = 0 + self._character_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if is_unprintable(character): + self._unprintable_count += 1 + self._character_count += 1 + + def reset(self) -> None: # pragma: no cover + self._unprintable_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._unprintable_count * 8) / self._character_count + + +class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._successive_count: int = 0 + self._character_count: int = 0 + + self._last_latin_character: Optional[str] = None + + def eligible(self, character: str) -> bool: + return character.isalpha() and is_latin(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + if ( + self._last_latin_character is not None + and is_accentuated(character) + and is_accentuated(self._last_latin_character) + ): + if character.isupper() and self._last_latin_character.isupper(): + self._successive_count += 1 + # Worse if its the same char duplicated with different accent. + if remove_accent(character) == remove_accent(self._last_latin_character): + self._successive_count += 1 + self._last_latin_character = character + + def reset(self) -> None: # pragma: no cover + self._successive_count = 0 + self._character_count = 0 + self._last_latin_character = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._successive_count * 2) / self._character_count + + +class SuspiciousRange(MessDetectorPlugin): + def __init__(self) -> None: + self._suspicious_successive_range_count: int = 0 + self._character_count: int = 0 + self._last_printable_seen: Optional[str] = None + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character.isspace() + or is_punctuation(character) + or character in COMMON_SAFE_ASCII_CHARACTERS + ): + self._last_printable_seen = None + return + + if self._last_printable_seen is None: + self._last_printable_seen = character + return + + unicode_range_a: Optional[str] = unicode_range(self._last_printable_seen) + unicode_range_b: Optional[str] = unicode_range(character) + + if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): + self._suspicious_successive_range_count += 1 + + self._last_printable_seen = character + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._suspicious_successive_range_count = 0 + self._last_printable_seen = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + ratio_of_suspicious_range_usage: float = ( + self._suspicious_successive_range_count * 2 + ) / self._character_count + + if ratio_of_suspicious_range_usage < 0.1: + return 0.0 + + return ratio_of_suspicious_range_usage + + +class SuperWeirdWordPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._word_count: int = 0 + self._bad_word_count: int = 0 + self._foreign_long_count: int = 0 + + self._is_current_word_bad: bool = False + self._foreign_long_watch: bool = False + + self._character_count: int = 0 + self._bad_character_count: int = 0 + + self._buffer: str = "" + self._buffer_accent_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character.isalpha(): + self._buffer += character + if is_accentuated(character): + self._buffer_accent_count += 1 + if ( + self._foreign_long_watch is False + and (is_latin(character) is False or is_accentuated(character)) + and is_cjk(character) is False + and is_hangul(character) is False + and is_katakana(character) is False + and is_hiragana(character) is False + and is_thai(character) is False + ): + self._foreign_long_watch = True + return + if not self._buffer: + return + if ( + character.isspace() or is_punctuation(character) or is_separator(character) + ) and self._buffer: + self._word_count += 1 + buffer_length: int = len(self._buffer) + + self._character_count += buffer_length + + if buffer_length >= 4: + if self._buffer_accent_count / buffer_length > 0.34: + self._is_current_word_bad = True + # Word/Buffer ending with a upper case accentuated letter are so rare, + # that we will consider them all as suspicious. Same weight as foreign_long suspicious. + if is_accentuated(self._buffer[-1]) and self._buffer[-1].isupper(): + self._foreign_long_count += 1 + self._is_current_word_bad = True + if buffer_length >= 24 and self._foreign_long_watch: + self._foreign_long_count += 1 + self._is_current_word_bad = True + + if self._is_current_word_bad: + self._bad_word_count += 1 + self._bad_character_count += len(self._buffer) + self._is_current_word_bad = False + + self._foreign_long_watch = False + self._buffer = "" + self._buffer_accent_count = 0 + elif ( + character not in {"<", ">", "-", "=", "~", "|", "_"} + and character.isdigit() is False + and is_symbol(character) + ): + self._is_current_word_bad = True + self._buffer += character + + def reset(self) -> None: # pragma: no cover + self._buffer = "" + self._is_current_word_bad = False + self._foreign_long_watch = False + self._bad_word_count = 0 + self._word_count = 0 + self._character_count = 0 + self._bad_character_count = 0 + self._foreign_long_count = 0 + + @property + def ratio(self) -> float: + if self._word_count <= 10 and self._foreign_long_count == 0: + return 0.0 + + return self._bad_character_count / self._character_count + + +class CjkInvalidStopPlugin(MessDetectorPlugin): + """ + GB(Chinese) based encoding often render the stop incorrectly when the content does not fit and + can be easily detected. Searching for the overuse of '丅' and '丄'. + """ + + def __init__(self) -> None: + self._wrong_stop_count: int = 0 + self._cjk_character_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character in {"丅", "丄"}: + self._wrong_stop_count += 1 + return + if is_cjk(character): + self._cjk_character_count += 1 + + def reset(self) -> None: # pragma: no cover + self._wrong_stop_count = 0 + self._cjk_character_count = 0 + + @property + def ratio(self) -> float: + if self._cjk_character_count < 16: + return 0.0 + return self._wrong_stop_count / self._cjk_character_count + + +class ArchaicUpperLowerPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._buf: bool = False + + self._character_count_since_last_sep: int = 0 + + self._successive_upper_lower_count: int = 0 + self._successive_upper_lower_count_final: int = 0 + + self._character_count: int = 0 + + self._last_alpha_seen: Optional[str] = None + self._current_ascii_only: bool = True + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + is_concerned = character.isalpha() and is_case_variable(character) + chunk_sep = is_concerned is False + + if chunk_sep and self._character_count_since_last_sep > 0: + if ( + self._character_count_since_last_sep <= 64 + and character.isdigit() is False + and self._current_ascii_only is False + ): + self._successive_upper_lower_count_final += ( + self._successive_upper_lower_count + ) + + self._successive_upper_lower_count = 0 + self._character_count_since_last_sep = 0 + self._last_alpha_seen = None + self._buf = False + self._character_count += 1 + self._current_ascii_only = True + + return + + if self._current_ascii_only is True and is_ascii(character) is False: + self._current_ascii_only = False + + if self._last_alpha_seen is not None: + if (character.isupper() and self._last_alpha_seen.islower()) or ( + character.islower() and self._last_alpha_seen.isupper() + ): + if self._buf is True: + self._successive_upper_lower_count += 2 + self._buf = False + else: + self._buf = True + else: + self._buf = False + + self._character_count += 1 + self._character_count_since_last_sep += 1 + self._last_alpha_seen = character + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._character_count_since_last_sep = 0 + self._successive_upper_lower_count = 0 + self._successive_upper_lower_count_final = 0 + self._last_alpha_seen = None + self._buf = False + self._current_ascii_only = True + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return self._successive_upper_lower_count_final / self._character_count + + +@lru_cache(maxsize=1024) +def is_suspiciously_successive_range( + unicode_range_a: Optional[str], unicode_range_b: Optional[str] +) -> bool: + """ + Determine if two Unicode range seen next to each other can be considered as suspicious. + """ + if unicode_range_a is None or unicode_range_b is None: + return True + + if unicode_range_a == unicode_range_b: + return False + + if "Latin" in unicode_range_a and "Latin" in unicode_range_b: + return False + + if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: + return False + + # Latin characters can be accompanied with a combining diacritical mark + # eg. Vietnamese. + if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( + "Combining" in unicode_range_a or "Combining" in unicode_range_b + ): + return False + + keywords_range_a, keywords_range_b = unicode_range_a.split( + " " + ), unicode_range_b.split(" ") + + for el in keywords_range_a: + if el in UNICODE_SECONDARY_RANGE_KEYWORD: + continue + if el in keywords_range_b: + return False + + # Japanese Exception + range_a_jp_chars, range_b_jp_chars = ( + unicode_range_a + in ( + "Hiragana", + "Katakana", + ), + unicode_range_b in ("Hiragana", "Katakana"), + ) + if (range_a_jp_chars or range_b_jp_chars) and ( + "CJK" in unicode_range_a or "CJK" in unicode_range_b + ): + return False + if range_a_jp_chars and range_b_jp_chars: + return False + + if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: + if "CJK" in unicode_range_a or "CJK" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + # Chinese/Japanese use dedicated range for punctuation and/or separators. + if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( + unicode_range_a in ["Katakana", "Hiragana"] + and unicode_range_b in ["Katakana", "Hiragana"] + ): + if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: + return False + if "Forms" in unicode_range_a or "Forms" in unicode_range_b: + return False + + return True + + +@lru_cache(maxsize=2048) +def mess_ratio( + decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False +) -> float: + """ + Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. + """ + + detectors: List[MessDetectorPlugin] = [ + md_class() for md_class in MessDetectorPlugin.__subclasses__() + ] + + length: int = len(decoded_sequence) + 1 + + mean_mess_ratio: float = 0.0 + + if length < 512: + intermediary_mean_mess_ratio_calc: int = 32 + elif length <= 1024: + intermediary_mean_mess_ratio_calc = 64 + else: + intermediary_mean_mess_ratio_calc = 128 + + for character, index in zip(decoded_sequence + "\n", range(length)): + for detector in detectors: + if detector.eligible(character): + detector.feed(character) + + if ( + index > 0 and index % intermediary_mean_mess_ratio_calc == 0 + ) or index == length - 1: + mean_mess_ratio = sum(dt.ratio for dt in detectors) + + if mean_mess_ratio >= maximum_threshold: + break + + if debug: + for dt in detectors: # pragma: nocover + print(dt.__class__, dt.ratio) + + return round(mean_mess_ratio, 3) diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/models.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/models.py new file mode 100644 index 0000000..ccb0d47 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/models.py @@ -0,0 +1,401 @@ +import warnings +from collections import Counter +from encodings.aliases import aliases +from hashlib import sha256 +from json import dumps +from re import sub +from typing import ( + Any, + Counter as TypeCounter, + Dict, + Iterator, + List, + Optional, + Tuple, + Union, +) + +from .constant import NOT_PRINTABLE_PATTERN, TOO_BIG_SEQUENCE +from .md import mess_ratio +from .utils import iana_name, is_multi_byte_encoding, unicode_range + + +class CharsetMatch: + def __init__( + self, + payload: bytes, + guessed_encoding: str, + mean_mess_ratio: float, + has_sig_or_bom: bool, + languages: "CoherenceMatches", + decoded_payload: Optional[str] = None, + ): + self._payload: bytes = payload + + self._encoding: str = guessed_encoding + self._mean_mess_ratio: float = mean_mess_ratio + self._languages: CoherenceMatches = languages + self._has_sig_or_bom: bool = has_sig_or_bom + self._unicode_ranges: Optional[List[str]] = None + + self._leaves: List[CharsetMatch] = [] + self._mean_coherence_ratio: float = 0.0 + + self._output_payload: Optional[bytes] = None + self._output_encoding: Optional[str] = None + + self._string: Optional[str] = decoded_payload + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CharsetMatch): + raise TypeError( + "__eq__ cannot be invoked on {} and {}.".format( + str(other.__class__), str(self.__class__) + ) + ) + return self.encoding == other.encoding and self.fingerprint == other.fingerprint + + def __lt__(self, other: object) -> bool: + """ + Implemented to make sorted available upon CharsetMatches items. + """ + if not isinstance(other, CharsetMatch): + raise ValueError + + chaos_difference: float = abs(self.chaos - other.chaos) + coherence_difference: float = abs(self.coherence - other.coherence) + + # Bellow 1% difference --> Use Coherence + if chaos_difference < 0.01 and coherence_difference > 0.02: + # When having a tough decision, use the result that decoded as many multi-byte as possible. + if chaos_difference == 0.0 and self.coherence == other.coherence: + return self.multi_byte_usage > other.multi_byte_usage + return self.coherence > other.coherence + + return self.chaos < other.chaos + + @property + def multi_byte_usage(self) -> float: + return 1.0 - len(str(self)) / len(self.raw) + + @property + def chaos_secondary_pass(self) -> float: + """ + Check once again chaos in decoded text, except this time, with full content. + Use with caution, this can be very slow. + Notice: Will be removed in 3.0 + """ + warnings.warn( + "chaos_secondary_pass is deprecated and will be removed in 3.0", + DeprecationWarning, + ) + return mess_ratio(str(self), 1.0) + + @property + def coherence_non_latin(self) -> float: + """ + Coherence ratio on the first non-latin language detected if ANY. + Notice: Will be removed in 3.0 + """ + warnings.warn( + "coherence_non_latin is deprecated and will be removed in 3.0", + DeprecationWarning, + ) + return 0.0 + + @property + def w_counter(self) -> TypeCounter[str]: + """ + Word counter instance on decoded text. + Notice: Will be removed in 3.0 + """ + warnings.warn( + "w_counter is deprecated and will be removed in 3.0", DeprecationWarning + ) + + string_printable_only = sub(NOT_PRINTABLE_PATTERN, " ", str(self).lower()) + + return Counter(string_printable_only.split()) + + def __str__(self) -> str: + # Lazy Str Loading + if self._string is None: + self._string = str(self._payload, self._encoding, "strict") + return self._string + + def __repr__(self) -> str: + return "".format(self.encoding, self.fingerprint) + + def add_submatch(self, other: "CharsetMatch") -> None: + if not isinstance(other, CharsetMatch) or other == self: + raise ValueError( + "Unable to add instance <{}> as a submatch of a CharsetMatch".format( + other.__class__ + ) + ) + + other._string = None # Unload RAM usage; dirty trick. + self._leaves.append(other) + + @property + def encoding(self) -> str: + return self._encoding + + @property + def encoding_aliases(self) -> List[str]: + """ + Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. + """ + also_known_as: List[str] = [] + for u, p in aliases.items(): + if self.encoding == u: + also_known_as.append(p) + elif self.encoding == p: + also_known_as.append(u) + return also_known_as + + @property + def bom(self) -> bool: + return self._has_sig_or_bom + + @property + def byte_order_mark(self) -> bool: + return self._has_sig_or_bom + + @property + def languages(self) -> List[str]: + """ + Return the complete list of possible languages found in decoded sequence. + Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. + """ + return [e[0] for e in self._languages] + + @property + def language(self) -> str: + """ + Most probable language found in decoded sequence. If none were detected or inferred, the property will return + "Unknown". + """ + if not self._languages: + # Trying to infer the language based on the given encoding + # Its either English or we should not pronounce ourselves in certain cases. + if "ascii" in self.could_be_from_charset: + return "English" + + # doing it there to avoid circular import + from charset_normalizer.cd import encoding_languages, mb_encoding_languages + + languages = ( + mb_encoding_languages(self.encoding) + if is_multi_byte_encoding(self.encoding) + else encoding_languages(self.encoding) + ) + + if len(languages) == 0 or "Latin Based" in languages: + return "Unknown" + + return languages[0] + + return self._languages[0][0] + + @property + def chaos(self) -> float: + return self._mean_mess_ratio + + @property + def coherence(self) -> float: + if not self._languages: + return 0.0 + return self._languages[0][1] + + @property + def percent_chaos(self) -> float: + return round(self.chaos * 100, ndigits=3) + + @property + def percent_coherence(self) -> float: + return round(self.coherence * 100, ndigits=3) + + @property + def raw(self) -> bytes: + """ + Original untouched bytes. + """ + return self._payload + + @property + def submatch(self) -> List["CharsetMatch"]: + return self._leaves + + @property + def has_submatch(self) -> bool: + return len(self._leaves) > 0 + + @property + def alphabets(self) -> List[str]: + if self._unicode_ranges is not None: + return self._unicode_ranges + # list detected ranges + detected_ranges: List[Optional[str]] = [ + unicode_range(char) for char in str(self) + ] + # filter and sort + self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) + return self._unicode_ranges + + @property + def could_be_from_charset(self) -> List[str]: + """ + The complete list of encoding that output the exact SAME str result and therefore could be the originating + encoding. + This list does include the encoding available in property 'encoding'. + """ + return [self._encoding] + [m.encoding for m in self._leaves] + + def first(self) -> "CharsetMatch": + """ + Kept for BC reasons. Will be removed in 3.0. + """ + return self + + def best(self) -> "CharsetMatch": + """ + Kept for BC reasons. Will be removed in 3.0. + """ + return self + + def output(self, encoding: str = "utf_8") -> bytes: + """ + Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. + Any errors will be simply ignored by the encoder NOT replaced. + """ + if self._output_encoding is None or self._output_encoding != encoding: + self._output_encoding = encoding + self._output_payload = str(self).encode(encoding, "replace") + + return self._output_payload # type: ignore + + @property + def fingerprint(self) -> str: + """ + Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. + """ + return sha256(self.output()).hexdigest() + + +class CharsetMatches: + """ + Container with every CharsetMatch items ordered by default from most probable to the less one. + Act like a list(iterable) but does not implements all related methods. + """ + + def __init__(self, results: Optional[List[CharsetMatch]] = None): + self._results: List[CharsetMatch] = sorted(results) if results else [] + + def __iter__(self) -> Iterator[CharsetMatch]: + yield from self._results + + def __getitem__(self, item: Union[int, str]) -> CharsetMatch: + """ + Retrieve a single item either by its position or encoding name (alias may be used here). + Raise KeyError upon invalid index or encoding not present in results. + """ + if isinstance(item, int): + return self._results[item] + if isinstance(item, str): + item = iana_name(item, False) + for result in self._results: + if item in result.could_be_from_charset: + return result + raise KeyError + + def __len__(self) -> int: + return len(self._results) + + def __bool__(self) -> bool: + return len(self._results) > 0 + + def append(self, item: CharsetMatch) -> None: + """ + Insert a single match. Will be inserted accordingly to preserve sort. + Can be inserted as a submatch. + """ + if not isinstance(item, CharsetMatch): + raise ValueError( + "Cannot append instance '{}' to CharsetMatches".format( + str(item.__class__) + ) + ) + # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) + if len(item.raw) <= TOO_BIG_SEQUENCE: + for match in self._results: + if match.fingerprint == item.fingerprint and match.chaos == item.chaos: + match.add_submatch(item) + return + self._results.append(item) + self._results = sorted(self._results) + + def best(self) -> Optional["CharsetMatch"]: + """ + Simply return the first match. Strict equivalent to matches[0]. + """ + if not self._results: + return None + return self._results[0] + + def first(self) -> Optional["CharsetMatch"]: + """ + Redundant method, call the method best(). Kept for BC reasons. + """ + return self.best() + + +CoherenceMatch = Tuple[str, float] +CoherenceMatches = List[CoherenceMatch] + + +class CliDetectionResult: + def __init__( + self, + path: str, + encoding: Optional[str], + encoding_aliases: List[str], + alternative_encodings: List[str], + language: str, + alphabets: List[str], + has_sig_or_bom: bool, + chaos: float, + coherence: float, + unicode_path: Optional[str], + is_preferred: bool, + ): + self.path: str = path + self.unicode_path: Optional[str] = unicode_path + self.encoding: Optional[str] = encoding + self.encoding_aliases: List[str] = encoding_aliases + self.alternative_encodings: List[str] = alternative_encodings + self.language: str = language + self.alphabets: List[str] = alphabets + self.has_sig_or_bom: bool = has_sig_or_bom + self.chaos: float = chaos + self.coherence: float = coherence + self.is_preferred: bool = is_preferred + + @property + def __dict__(self) -> Dict[str, Any]: # type: ignore + return { + "path": self.path, + "encoding": self.encoding, + "encoding_aliases": self.encoding_aliases, + "alternative_encodings": self.alternative_encodings, + "language": self.language, + "alphabets": self.alphabets, + "has_sig_or_bom": self.has_sig_or_bom, + "chaos": self.chaos, + "coherence": self.coherence, + "unicode_path": self.unicode_path, + "is_preferred": self.is_preferred, + } + + def to_json(self) -> str: + return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/py.typed b/axios-example/lib/python3.10/site-packages/charset_normalizer/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/utils.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/utils.py new file mode 100644 index 0000000..859f212 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/utils.py @@ -0,0 +1,424 @@ +try: + # WARNING: unicodedata2 support is going to be removed in 3.0 + # Python is quickly catching up. + import unicodedata2 as unicodedata +except ImportError: + import unicodedata # type: ignore[no-redef] + +import importlib +import logging +from codecs import IncrementalDecoder +from encodings.aliases import aliases +from functools import lru_cache +from re import findall +from typing import Generator, List, Optional, Set, Tuple, Union + +from _multibytecodec import MultibyteIncrementalDecoder + +from .constant import ( + ENCODING_MARKS, + IANA_SUPPORTED_SIMILAR, + RE_POSSIBLE_ENCODING_INDICATION, + UNICODE_RANGES_COMBINED, + UNICODE_SECONDARY_RANGE_KEYWORD, + UTF8_MAXIMAL_ALLOCATION, +) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_accentuated(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: + return False + return ( + "WITH GRAVE" in description + or "WITH ACUTE" in description + or "WITH CEDILLA" in description + or "WITH DIAERESIS" in description + or "WITH CIRCUMFLEX" in description + or "WITH TILDE" in description + ) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def remove_accent(character: str) -> str: + decomposed: str = unicodedata.decomposition(character) + if not decomposed: + return character + + codes: List[str] = decomposed.split(" ") + + return chr(int(codes[0], 16)) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def unicode_range(character: str) -> Optional[str]: + """ + Retrieve the Unicode range official name from a single character. + """ + character_ord: int = ord(character) + + for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): + if character_ord in ord_range: + return range_name + + return None + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_latin(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: + return False + return "LATIN" in description + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_ascii(character: str) -> bool: + try: + character.encode("ascii") + except UnicodeEncodeError: + return False + return True + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_punctuation(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "P" in character_category: + return True + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Punctuation" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_symbol(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "S" in character_category or "N" in character_category: + return True + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Forms" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_emoticon(character: str) -> bool: + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Emoticons" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_separator(character: str) -> bool: + if character.isspace() or character in {"|", "+", ",", ";", "<", ">"}: + return True + + character_category: str = unicodedata.category(character) + + return "Z" in character_category + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_case_variable(character: str) -> bool: + return character.islower() != character.isupper() + + +def is_private_use_only(character: str) -> bool: + character_category: str = unicodedata.category(character) + + return character_category == "Co" + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_cjk(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "CJK" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hiragana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "HIRAGANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_katakana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "KATAKANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hangul(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "HANGUL" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_thai(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "THAI" in character_name + + +@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) +def is_unicode_range_secondary(range_name: str) -> bool: + return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_unprintable(character: str) -> bool: + return ( + character.isspace() is False # includes \n \t \r \v + and character.isprintable() is False + and character != "\x1A" # Why? Its the ASCII substitute character. + and character != "\ufeff" # bug discovered in Python, + # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. + ) + + +def any_specified_encoding(sequence: bytes, search_zone: int = 4096) -> Optional[str]: + """ + Extract using ASCII-only decoder any specified encoding in the first n-bytes. + """ + if not isinstance(sequence, bytes): + raise TypeError + + seq_len: int = len(sequence) + + results: List[str] = findall( + RE_POSSIBLE_ENCODING_INDICATION, + sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), + ) + + if len(results) == 0: + return None + + for specified_encoding in results: + specified_encoding = specified_encoding.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if encoding_alias == specified_encoding: + return encoding_iana + if encoding_iana == specified_encoding: + return encoding_iana + + return None + + +@lru_cache(maxsize=128) +def is_multi_byte_encoding(name: str) -> bool: + """ + Verify is a specific encoding is a multi byte one based on it IANA name + """ + return name in { + "utf_8", + "utf_8_sig", + "utf_16", + "utf_16_be", + "utf_16_le", + "utf_32", + "utf_32_le", + "utf_32_be", + "utf_7", + } or issubclass( + importlib.import_module("encodings.{}".format(name)).IncrementalDecoder, + MultibyteIncrementalDecoder, + ) + + +def identify_sig_or_bom(sequence: bytes) -> Tuple[Optional[str], bytes]: + """ + Identify and extract SIG/BOM in given sequence. + """ + + for iana_encoding in ENCODING_MARKS: + marks: Union[bytes, List[bytes]] = ENCODING_MARKS[iana_encoding] + + if isinstance(marks, bytes): + marks = [marks] + + for mark in marks: + if sequence.startswith(mark): + return iana_encoding, mark + + return None, b"" + + +def should_strip_sig_or_bom(iana_encoding: str) -> bool: + return iana_encoding not in {"utf_16", "utf_32"} + + +def iana_name(cp_name: str, strict: bool = True) -> str: + cp_name = cp_name.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if cp_name in [encoding_alias, encoding_iana]: + return encoding_iana + + if strict: + raise ValueError("Unable to retrieve IANA for '{}'".format(cp_name)) + + return cp_name + + +def range_scan(decoded_sequence: str) -> List[str]: + ranges: Set[str] = set() + + for character in decoded_sequence: + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + continue + + ranges.add(character_range) + + return list(ranges) + + +def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: + + if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): + return 0.0 + + decoder_a = importlib.import_module( + "encodings.{}".format(iana_name_a) + ).IncrementalDecoder + decoder_b = importlib.import_module( + "encodings.{}".format(iana_name_b) + ).IncrementalDecoder + + id_a: IncrementalDecoder = decoder_a(errors="ignore") + id_b: IncrementalDecoder = decoder_b(errors="ignore") + + character_match_count: int = 0 + + for i in range(255): + to_be_decoded: bytes = bytes([i]) + if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): + character_match_count += 1 + + return character_match_count / 254 + + +def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: + """ + Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using + the function cp_similarity. + """ + return ( + iana_name_a in IANA_SUPPORTED_SIMILAR + and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] + ) + + +def set_logging_handler( + name: str = "charset_normalizer", + level: int = logging.INFO, + format_string: str = "%(asctime)s | %(levelname)s | %(message)s", +) -> None: + + logger = logging.getLogger(name) + logger.setLevel(level) + + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(format_string)) + logger.addHandler(handler) + + +def cut_sequence_chunks( + sequences: bytes, + encoding_iana: str, + offsets: range, + chunk_size: int, + bom_or_sig_available: bool, + strip_sig_or_bom: bool, + sig_payload: bytes, + is_multi_byte_decoder: bool, + decoded_payload: Optional[str] = None, +) -> Generator[str, None, None]: + + if decoded_payload and is_multi_byte_decoder is False: + for i in offsets: + chunk = decoded_payload[i : i + chunk_size] + if not chunk: + break + yield chunk + else: + for i in offsets: + chunk_end = i + chunk_size + if chunk_end > len(sequences) + 8: + continue + + cut_sequence = sequences[i : i + chunk_size] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode( + encoding_iana, + errors="ignore" if is_multi_byte_decoder else "strict", + ) + + # multi-byte bad cutting detector and adjustment + # not the cleanest way to perform that fix but clever enough for now. + if is_multi_byte_decoder and i > 0 and sequences[i] >= 0x80: + + chunk_partial_size_chk: int = min(chunk_size, 16) + + if ( + decoded_payload + and chunk[:chunk_partial_size_chk] not in decoded_payload + ): + for j in range(i, i - 4, -1): + cut_sequence = sequences[j:chunk_end] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode(encoding_iana, errors="ignore") + + if chunk[:chunk_partial_size_chk] in decoded_payload: + break + + yield chunk diff --git a/axios-example/lib/python3.10/site-packages/charset_normalizer/version.py b/axios-example/lib/python3.10/site-packages/charset_normalizer/version.py new file mode 100644 index 0000000..64c0dbd --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/charset_normalizer/version.py @@ -0,0 +1,6 @@ +""" +Expose version +""" + +__version__ = "2.1.1" +VERSION = __version__.split(".") diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA new file mode 100644 index 0000000..8e5dc1e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA @@ -0,0 +1,111 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.1.3 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: colorama ; platform_system == "Windows" +Requires-Dist: importlib-metadata ; python_version < "3.8" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Website: https://palletsprojects.com/p/click +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD new file mode 100644 index 0000000..cc524e6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD @@ -0,0 +1,40 @@ +click-8.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.3.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.3.dist-info/METADATA,sha256=tFJIX5lOjx7c5LjZbdTPFVDJSgyv9F74XY0XCPp_gnc,3247 +click-8.1.3.dist-info/RECORD,, +click-8.1.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click-8.1.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +click-8.1.3.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click/__init__.py,sha256=rQBLutqg-z6m8nOzivIfigDn_emijB_dKv9BZ2FNi5s,3138 +click/__pycache__/__init__.cpython-310.pyc,, +click/__pycache__/_compat.cpython-310.pyc,, +click/__pycache__/_termui_impl.cpython-310.pyc,, +click/__pycache__/_textwrap.cpython-310.pyc,, +click/__pycache__/_winconsole.cpython-310.pyc,, +click/__pycache__/core.cpython-310.pyc,, +click/__pycache__/decorators.cpython-310.pyc,, +click/__pycache__/exceptions.cpython-310.pyc,, +click/__pycache__/formatting.cpython-310.pyc,, +click/__pycache__/globals.cpython-310.pyc,, +click/__pycache__/parser.cpython-310.pyc,, +click/__pycache__/shell_completion.cpython-310.pyc,, +click/__pycache__/termui.cpython-310.pyc,, +click/__pycache__/testing.cpython-310.pyc,, +click/__pycache__/types.cpython-310.pyc,, +click/__pycache__/utils.cpython-310.pyc,, +click/_compat.py,sha256=JIHLYs7Jzz4KT9t-ds4o4jBzLjnwCiJQKqur-5iwCKI,18810 +click/_termui_impl.py,sha256=qK6Cfy4mRFxvxE8dya8RBhLpSC8HjF-lvBc6aNrPdwg,23451 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=mz87bYEKzIoNYEa56BFAiOJnvt1Y0L-i7wD4_ZecieE,112782 +click/decorators.py,sha256=yo3zvzgUm5q7h5CXjyV6q3h_PJAiUaem178zXwdWUFI,16350 +click/exceptions.py,sha256=7gDaLGuFZBeCNwY9ERMsF2-Z3R9Fvq09Zc6IZSKjseo,9167 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961 +click/parser.py,sha256=cAEt1uQR8gq3-S9ysqbVU-fdAZNvilxw4ReJ_T1OQMk,19044 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=qOp_BeC9esEOSZKyu5G7RIxEUaLsXUX-mTb7hB1r4QY,18018 +click/termui.py,sha256=ACBQVOvFCTSqtD5VREeCAdRtlHd-Imla-Lte4wSfMjA,28355 +click/testing.py,sha256=ptpMYgRY7dVfE3UDgkgwayu9ePw98sQI3D7zZXiCpj4,16063 +click/types.py,sha256=rEb1aZSQKq3ciCMmjpG2Uva9vk498XRL7ThrcK2GRss,35805 +click/utils.py,sha256=33D6E7poH_nrKB-xr-UyDEXnxOcCiQqxuRLtrqeVv6o,18682 diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt new file mode 100644 index 0000000..dca9a90 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/axios-example/lib/python3.10/site-packages/click/__init__.py b/axios-example/lib/python3.10/site-packages/click/__init__.py new file mode 100644 index 0000000..e3ef423 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/__init__.py @@ -0,0 +1,73 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.3" diff --git a/axios-example/lib/python3.10/site-packages/click/_compat.py b/axios-example/lib/python3.10/site-packages/click/_compat.py new file mode 100644 index 0000000..766d286 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/_compat.py @@ -0,0 +1,626 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +MSYS2 = sys.platform.startswith("win") and ("GCC" in sys.version) +# Determine local App Engine environment, per Google's own suggestion +APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ.get( + "SERVER_SOFTWARE", "" +) +WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2 +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def get_filesystem_encoding() -> str: + return sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO, default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO, default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO, bool], bool], + find_binary: t.Callable[[t.IO], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, os.PathLike, int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO, bool]: + binary = "b" in mode + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO, af), True + + +class _AtomicFile: + def __init__(self, f: t.IO, tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.TextIO], wrapper_func: t.Callable[[], t.TextIO] +) -> t.Callable[[], t.TextIO]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.TextIO: + stream = src_func() + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/axios-example/lib/python3.10/site-packages/click/_termui_impl.py b/axios-example/lib/python3.10/site-packages/click/_termui_impl.py new file mode 100644 index 0000000..4b979bc --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/_termui_impl.py @@ -0,0 +1,717 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label = label or "" + if file is None: + file = _default_text_stdout() + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width = width + self.autowidth = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.start = self.last_eta = time.time() + self.eta_known = False + self.finished = False + self.max_width: t.Optional[int] = None + self.entered = False + self.current_item: t.Optional[V] = None + self.is_hidden = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar": + self.entered = True + self.render_progress() + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + return _tempfilepager(generator, pager_cmd, color) + return _pipepager(generator, pager_cmd, color) + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if WIN or sys.platform.startswith("os2"): + return _tempfilepager(generator, "more <", color) + if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: + return _pipepager(generator, "less", color) + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: + return _pipepager(generator, "more", color) + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) + try: + for text in generator: + if not color: + text = strip_ansi(text) + + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): + pass + else: + stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: + """Page through text by invoking a program on a temporary file.""" + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + os.system(f'{cmd} "{filename}"') + finally: + os.close(fd) + os.unlink(filename) + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if os.system(f"which {editor} >/dev/null 2>&1") == 0: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url.replace('"', "")) + args = f'explorer /select,"{url}"' + else: + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' + return os.system(args) + elif CYGWIN: + if locate: + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' + else: + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' + return os.system(args) + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import tty + import termios + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/axios-example/lib/python3.10/site-packages/click/_textwrap.py b/axios-example/lib/python3.10/site-packages/click/_textwrap.py new file mode 100644 index 0000000..b47dcbd --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> t.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/axios-example/lib/python3.10/site-packages/click/_winconsole.py b/axios-example/lib/python3.10/site-packages/click/_winconsole.py new file mode 100644 index 0000000..6b20df3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/_winconsole.py @@ -0,0 +1,279 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +import io +import sys +import time +import typing as t +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self): + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/axios-example/lib/python3.10/site-packages/click/core.py b/axios-example/lib/python3.10/site-packages/click/core.py new file mode 100644 index 0000000..5abfb0f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/core.py @@ -0,0 +1,2998 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import partial +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.Dict[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.Dict[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[ + t.Callable[[str], str] + ] = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional["Context"] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", t.Callable[..., t.Any]], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = other_cmd.callback + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.Dict[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, info_name=info_name, parent=parent, **extra # type: ignore + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invokable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt): + echo(file=sys.stderr) + raise Abort() from None + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + """ + if complete_var is None: + complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List["Parameter"] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + return Option( + help_options, + is_flag=True, + is_eager=True, + expose_value=False, + callback=show_help, + help=_("Show this message and exit."), + ) + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + text = self.help if self.help is not None else "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + text = inspect.cleandoc(text).partition("\f")[0] + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) # type: ignore + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commmands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[t.Union[t.Dict[str, Command], t.Sequence[Command]]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.Dict[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: + ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: + ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + func: t.Optional[t.Callable] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": + ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: + ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The later is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + convert: t.Callable[[t.Any], t.Any] = partial( + self.type, param=self, ctx=ctx + ) + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Tuple: + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Tuple: + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + if is_flag and default_is_missing and not self.required: + self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False + + if flag_value is None: + flag_value = not self.default + + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + if self.multiple and self.is_flag: + raise TypeError("'multiple' is not valid with 'is_flag', use 'count'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError("Could not determine name for option") + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if self.default else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return param.flag_value # type: ignore + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the parameter constructor. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Could not determine name for argument") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/axios-example/lib/python3.10/site-packages/click/decorators.py b/axios-example/lib/python3.10/site-packages/click/decorators.py new file mode 100644 index 0000000..28618dc --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/decorators.py @@ -0,0 +1,497 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +FC = t.TypeVar("FC", bound=t.Union[t.Callable[..., t.Any], Command]) + + +def pass_context(f: F) -> F: + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args, **kwargs): # type: ignore + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def pass_obj(f: F) -> F: + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args, **kwargs): # type: ignore + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def make_pass_decorator( + object_type: t.Type, ensure: bool = False +) -> "t.Callable[[F], F]": + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[F], F]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +@t.overload +def command( + __func: t.Callable[..., t.Any], +) -> Command: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[..., Command]: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + cls: t.Type[CmdType] = ..., + **attrs: t.Any, +) -> t.Callable[..., CmdType]: + ... + + +def command( + name: t.Union[str, t.Callable[..., t.Any], None] = None, + cls: t.Optional[t.Type[Command]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[..., Command]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[..., t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = Command + + def decorator(f: t.Callable[..., t.Any]) -> Command: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + cmd = cls( # type: ignore[misc] + name=name or f.__name__.lower().replace("_", "-"), # type: ignore[arg-type] + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +@t.overload +def group( + __func: t.Callable[..., t.Any], +) -> Group: + ... + + +@t.overload +def group( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[[F], Group]: + ... + + +def group( + name: t.Union[str, t.Callable[..., t.Any], None] = None, **attrs: t.Any +) -> t.Union[Group, t.Callable[[F], Group]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if attrs.get("cls") is None: + attrs["cls"] = Group + + if callable(name): + grp: t.Callable[[F], Group] = t.cast(Group, command(**attrs)) + return grp(name) + + return t.cast(Group, command(name, **attrs)) + + +def _param_memo(f: FC, param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + """ + + def decorator(f: FC) -> FC: + ArgumentClass = attrs.pop("cls", None) or Argument + _param_memo(f, ArgumentClass(param_decls, **attrs)) + return f + + return decorator + + +def option(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + """ + + def decorator(f: FC) -> FC: + # Issue 926, copy attrs, so pre-defined options can re-use the same cls= + option_attrs = attrs.copy() + OptionClass = option_attrs.pop("cls", None) or Option + _param_memo(f, OptionClass(param_decls, **option_attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + t.cast(str, message) + % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/axios-example/lib/python3.10/site-packages/click/exceptions.py b/axios-example/lib/python3.10/site-packages/click/exceptions.py new file mode 100644 index 0000000..9e20b3e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/exceptions.py @@ -0,0 +1,287 @@ +import os +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .utils import echo + +if t.TYPE_CHECKING: + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO] = None) -> None: + if file is None: + file = get_text_stderr() + + echo(_("Error: {message}").format(message=self.format_message()), file=file) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename = os.fsdecode(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code = code diff --git a/axios-example/lib/python3.10/site-packages/click/formatting.py b/axios-example/lib/python3.10/site-packages/click/formatting.py new file mode 100644 index 0000000..ddd2a2f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer: t.List[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> t.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> t.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/axios-example/lib/python3.10/site-packages/click/globals.py b/axios-example/lib/python3.10/site-packages/click/globals.py new file mode 100644 index 0000000..480058f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/globals.py @@ -0,0 +1,68 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/axios-example/lib/python3.10/site-packages/click/parser.py b/axios-example/lib/python3.10/site-packages/click/parser.py new file mode 100644 index 0000000..2d5a2ed --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/parser.py @@ -0,0 +1,529 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: str, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List["CoreParameter"] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we re-combinate the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/axios-example/lib/python3.10/site-packages/click/py.typed b/axios-example/lib/python3.10/site-packages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/click/shell_completion.py b/axios-example/lib/python3.10/site-packages/click/shell_completion.py new file mode 100644 index 0000000..c17a8e6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/shell_completion.py @@ -0,0 +1,580 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value = value + self.type = type + self.help = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +compdef %(complete_func)s %(prog_name)s; +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response; + + for value in (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + set response $response $value; + end; + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + def _check_version(self) -> None: + import subprocess + + output = subprocess.run( + ["bash", "-c", "echo ${BASH_VERSION}"], stdout=subprocess.PIPE + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + raise RuntimeError( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ) + ) + else: + raise RuntimeError( + _("Couldn't detect Bash version, shell completion is not supported.") + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: t.Type[ShellComplete], name: t.Optional[str] = None +) -> None: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + value = ctx.params[param.name] + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, ctx_args: t.Dict[str, t.Any], prog_name: str, args: t.List[str] +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/axios-example/lib/python3.10/site-packages/click/termui.py b/axios-example/lib/python3.10/site-packages/click/termui.py new file mode 100644 index 0000000..bfb2f5a --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/termui.py @@ -0,0 +1,787 @@ +import inspect +import io +import itertools +import os +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from ._compat import WIN +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name # type: ignore + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + if WIN: + os.system("cls") + else: + sys.stdout.write("\033[2J\033[1;1H") + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/axios-example/lib/python3.10/site-packages/click/testing.py b/axios-example/lib/python3.10/site-packages/click/testing.py new file mode 100644 index 0000000..e395c2e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/testing.py @@ -0,0 +1,479 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO, input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(t.cast(bytes, input)) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) # type: ignore[type-var] + os.chdir(dt) + + try: + yield t.cast(str, dt) + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: # noqa: B014 + pass diff --git a/axios-example/lib/python3.10/site-packages/click/types.py b/axios-example/lib/python3.10/site-packages/click/types.py new file mode 100644 index 0000000..b45ee53 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/types.py @@ -0,0 +1,1073 @@ +import os +import stat +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import get_filesystem_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = get_filesystem_encoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Starting with Click 2.0, files can also be opened atomically in which + case all writes go into a separate file in the same folder and upon + completion the file will be moved over to the original location. This + is useful if a file regularly read by other users is modified. + + See :ref:`file-args` for more information. + """ + + name = "filename" + envvar_list_splitter = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: t.Any) -> bool: + if self.lazy is not None: + return self.lazy + if value == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + if hasattr(value, "read") or hasattr(value, "write"): + return value + + lazy = self.resolve_lazy_flag(value) + + if lazy: + f: t.IO = t.cast( + t.IO, + LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ), + ) + + if ctx is not None: + ctx.call_on_close(f.close_intelligently) # type: ignore + + return f + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: # noqa: B014 + self.fail(f"'{os.fsdecode(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result(self, rv: t.Any) -> t.Any: + if self.type is not None and not isinstance(rv, self.type): + if self.type is str: + rv = os.fsdecode(rv) + elif self.type is bytes: + rv = os.fsencode(rv) + else: + rv = self.type(rv) + + return rv + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} '{filename}' is a directory.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type, ParamType]]) -> None: + self.types = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/axios-example/lib/python3.10/site-packages/click/utils.py b/axios-example/lib/python3.10/site-packages/click/utils.py new file mode 100644 index 0000000..8283788 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/click/utils.py @@ -0,0 +1,580 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import get_filesystem_encoding +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: F) -> F: + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args, **kwargs): # type: ignore + try: + return func(*args, **kwargs) + except Exception: + pass + + return update_wrapper(t.cast(F, wrapper), func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(get_filesystem_encoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name = filename + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO] + + if filename == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: # noqa: E402 + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO) -> None: + self._file = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast(t.IO, LazyFile(filename, mode, encoding, errors, atomic=atomic)) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO, KeepOpenFile(f)) + + return f + + +def format_filename( + filename: t.Union[str, bytes, os.PathLike], shorten: bool = False +) -> str: + """Formats a filename for user display. The main purpose of this + function is to ensure that the filename can be displayed at all. This + will decode the filename to unicode if necessary in a way that it will + not fail. Optionally, it can shorten the filename to not include the + full path to the filename. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + + return os.fsdecode(filename) + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no affect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + if getattr(_main, "__package__", None) is None or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/axios-example/lib/python3.10/site-packages/distutils-precedence.pth b/axios-example/lib/python3.10/site-packages/distutils-precedence.pth new file mode 100644 index 0000000..7f009fe --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/distutils-precedence.pth @@ -0,0 +1 @@ +import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/LICENSE new file mode 100644 index 0000000..50d4fa5 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/LICENSE @@ -0,0 +1,73 @@ +The MIT License (MIT) + +Copyright (c) 2022 Alex Grönholm + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +This project contains code copied from the Python standard library. +The following is the required license notice for those parts. + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/METADATA new file mode 100644 index 0000000..be4d093 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/METADATA @@ -0,0 +1,141 @@ +Metadata-Version: 2.1 +Name: exceptiongroup +Version: 1.0.4 +Summary: Backport of PEP 654 (exception groups) +Author-email: Alex Grönholm +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Typing :: Typed +Requires-Dist: pytest >= 6 ; extra == "test" +Project-URL: Changelog, https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst +Project-URL: Issue Tracker, https://github.com/agronholm/exceptiongroup/issues +Project-URL: Source code, https://github.com/agronholm/exceptiongroup +Provides-Extra: test + +.. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg + :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml + :alt: Build Status +.. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main + :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main + :alt: Code Coverage + +This is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from +Python 3.11. + +It contains the following: + +* The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup`` + classes +* A utility function (``exceptiongroup.catch()``) for catching exceptions possibly + nested in an exception group +* Patches to the ``TracebackException`` class that properly formats exception groups + (installed on import) +* An exception hook that handles formatting of exception groups through + ``TracebackException`` (installed on import) +* Special versions of some of the functions from the ``traceback`` module, modified to + correctly handle exception groups even when monkey patching is disabled, or blocked by + another custom exception hook: + + * ``traceback.format_exception()`` + * ``traceback.format_exception_only()`` + * ``traceback.print_exception()`` + * ``traceback.print_exc()`` + +If this package is imported on Python 3.11 or later, the built-in implementations of the +exception group classes are used instead, ``TracebackException`` is not monkey patched +and the exception hook won't be installed. + +See the `standard library documentation`_ for more information on exception groups. + +.. _standard library documentation: https://docs.python.org/3/library/exceptions.html + +Catching exceptions +=================== + +Due to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python +versions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are +potentially nested inside an exception group. This function returns a context manager +that calls the given handler for any exceptions matching the sole argument. + +The argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either +an exception class or an iterable of exception classes. Each value must be a callable +that takes a single positional argument. The handler will be called at most once, with +an exception group as an argument which will contain all the exceptions that are any +of the given types, or their subclasses. The exception group may contain nested groups +containing more matching exceptions. + +Thus, the following Python 3.11+ code: + +.. code-block:: python3 + + try: + ... + except* (ValueError, KeyError) as excgroup: + for exc in excgroup.exceptions: + print('Caught exception:', type(exc)) + except* RuntimeError: + print('Caught runtime error') + +would be written with this backport like this: + +.. code-block:: python3 + + from exceptiongroup import ExceptionGroup, catch + + def value_key_err_handler(excgroup: ExceptionGroup) -> None: + for exc in excgroup.exceptions: + print('Caught exception:', type(exc)) + + def runtime_err_handler(exc: ExceptionGroup) -> None: + print('Caught runtime error') + + with catch({ + (ValueError, KeyError): value_key_err_handler, + RuntimeError: runtime_err_handler + }): + ... + +**NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or +``ExceptionGroup`` with ``catch()``. + +Notes on monkey patching +======================== + +To make exception groups render properly when an unhandled exception group is being +printed out, this package does two things when it is imported on any Python version +earlier than 3.11: + +#. The ``traceback.TracebackException`` class is monkey patched to store extra + information about exception groups (in ``__init__()``) and properly format them (in + ``format()``) +#. An exception hook is installed at ``sys.excepthook``, provided that no other hook is + already present. This hook causes the exception to be formatted using + ``traceback.TracebackException`` rather than the built-in rendered. + +If ``sys.exceptionhook`` is found to be set to something else than the default when +``exceptiongroup`` is imported, no monkeypatching is done at all. + +To prevent the exception hook and patches from being installed, set the environment +variable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``. + +Formatting exception groups +--------------------------- + +Normally, the monkey patching applied by this library on import will cause exception +groups to be printed properly in tracebacks. But in cases when the monkey patching is +blocked by a third party exception hook, or monkey patching is explicitly disabled, +you can still manually format exceptions using the special versions of the ``traceback`` +functions, like ``format_exception()``, listed at the top of this page. They work just +like their counterparts in the ``traceback`` module, except that they use a separately +patched subclass of ``TracebackException`` to perform the rendering. + +Particularly in cases where a library installs its own exception hook, it is recommended +to use these special versions to do the actual formatting of exceptions/tracebacks. + +.. _PEP 654: https://www.python.org/dev/peps/pep-0654/ + diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/RECORD new file mode 100644 index 0000000..e4b1e8b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/RECORD @@ -0,0 +1,16 @@ +exceptiongroup-1.0.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +exceptiongroup-1.0.4.dist-info/LICENSE,sha256=blBw12UDHgrUA6HL-Qrm0ZoCKPgC4yC3rP9GCqcu1Hw,3704 +exceptiongroup-1.0.4.dist-info/METADATA,sha256=OC66zYYnqbzPyOjVzWq00upl5X9pe1Jz1s3OPwkQWdA,6083 +exceptiongroup-1.0.4.dist-info/RECORD,, +exceptiongroup-1.0.4.dist-info/WHEEL,sha256=rSgq_JpHF9fHR1lx53qwg_1-2LypZE_qmcuXbVUq948,81 +exceptiongroup/__init__.py,sha256=Zr-MMWDXFMdrRBC8nS8UFqATRQL0Z-Lb-SANqs-uu0I,920 +exceptiongroup/__pycache__/__init__.cpython-310.pyc,, +exceptiongroup/__pycache__/_catch.cpython-310.pyc,, +exceptiongroup/__pycache__/_exceptions.cpython-310.pyc,, +exceptiongroup/__pycache__/_formatting.cpython-310.pyc,, +exceptiongroup/__pycache__/_version.cpython-310.pyc,, +exceptiongroup/_catch.py,sha256=m7BHRSU_kKy_pqMISPArf99zW1RgMG00i8623f7_sEo,3578 +exceptiongroup/_exceptions.py,sha256=cd6Awi65bB94Qr_jPznaMe8BRWPLtwBisu7Ppk8_MLM,9687 +exceptiongroup/_formatting.py,sha256=LBv947qWeg2foEXPwgJl9S9lp2bH4OfRlWqxqXYXOZg,19035 +exceptiongroup/_version.py,sha256=jBXjl_hABxpdVyNAw5ycdFE6qZsjSMVOiQTI0Wr25wE,176 +exceptiongroup/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/WHEEL new file mode 100644 index 0000000..db4a255 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup-1.0.4.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.8.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/__init__.py b/axios-example/lib/python3.10/site-packages/exceptiongroup/__init__.py new file mode 100644 index 0000000..0e7e02b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup/__init__.py @@ -0,0 +1,40 @@ +__all__ = [ + "BaseExceptionGroup", + "ExceptionGroup", + "catch", + "format_exception", + "format_exception_only", + "print_exception", + "print_exc", +] + +import os +import sys + +from ._catch import catch +from ._version import version as __version__ # noqa: F401 + +if sys.version_info < (3, 11): + from ._exceptions import BaseExceptionGroup, ExceptionGroup + from ._formatting import ( + format_exception, + format_exception_only, + print_exc, + print_exception, + ) + + if os.getenv("EXCEPTIONGROUP_NO_PATCH") != "1": + from . import _formatting # noqa: F401 + + BaseExceptionGroup.__module__ = __name__ + ExceptionGroup.__module__ = __name__ +else: + from traceback import ( + format_exception, + format_exception_only, + print_exc, + print_exception, + ) + + BaseExceptionGroup = BaseExceptionGroup + ExceptionGroup = ExceptionGroup diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/_catch.py b/axios-example/lib/python3.10/site-packages/exceptiongroup/_catch.py new file mode 100644 index 0000000..aa16d16 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup/_catch.py @@ -0,0 +1,114 @@ +from __future__ import annotations + +import sys +from collections.abc import Callable, Iterable, Mapping +from contextlib import AbstractContextManager +from types import TracebackType +from typing import TYPE_CHECKING, Any + +if sys.version_info < (3, 11): + from ._exceptions import BaseExceptionGroup + +if TYPE_CHECKING: + _Handler = Callable[[BaseException], Any] + + +class _Catcher: + def __init__(self, handler_map: Mapping[tuple[type[BaseException], ...], _Handler]): + self._handler_map = handler_map + + def __enter__(self) -> None: + pass + + def __exit__( + self, + etype: type[BaseException] | None, + exc: BaseException | None, + tb: TracebackType | None, + ) -> bool: + if exc is not None: + unhandled = self.handle_exception(exc) + if unhandled is exc: + return False + elif unhandled is None: + return True + else: + raise unhandled from None + + return False + + def handle_exception(self, exc: BaseException) -> BaseExceptionGroup | None: + excgroup: BaseExceptionGroup | None + if isinstance(exc, BaseExceptionGroup): + excgroup = exc + else: + excgroup = BaseExceptionGroup("", [exc]) + + new_exceptions: list[BaseException] = [] + for exc_types, handler in self._handler_map.items(): + matched, excgroup = excgroup.split(exc_types) + if matched: + try: + handler(matched) + except BaseException as new_exc: + new_exceptions.append(new_exc) + + if not excgroup: + break + + if new_exceptions: + if excgroup: + new_exceptions.append(excgroup) + + return BaseExceptionGroup("", new_exceptions) + elif ( + excgroup and len(excgroup.exceptions) == 1 and excgroup.exceptions[0] is exc + ): + return exc + else: + return excgroup + + +def catch( + __handlers: Mapping[type[BaseException] | Iterable[type[BaseException]], _Handler] +) -> AbstractContextManager[None]: + if not isinstance(__handlers, Mapping): + raise TypeError("the argument must be a mapping") + + handler_map: dict[ + tuple[type[BaseException], ...], Callable[[BaseExceptionGroup]] + ] = {} + for type_or_iterable, handler in __handlers.items(): + iterable: tuple[type[BaseException]] + if isinstance(type_or_iterable, type) and issubclass( + type_or_iterable, BaseException + ): + iterable = (type_or_iterable,) + elif isinstance(type_or_iterable, Iterable): + iterable = tuple(type_or_iterable) + else: + raise TypeError( + "each key must be either an exception classes or an iterable thereof" + ) + + if not callable(handler): + raise TypeError("handlers must be callable") + + for exc_type in iterable: + if not isinstance(exc_type, type) or not issubclass( + exc_type, BaseException + ): + raise TypeError( + "each key must be either an exception classes or an iterable " + "thereof" + ) + + if issubclass(exc_type, BaseExceptionGroup): + raise TypeError( + "catching ExceptionGroup with catch() is not allowed. " + "Use except instead." + ) + + handler_map[iterable] = handler + + return _Catcher(handler_map) diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/_exceptions.py b/axios-example/lib/python3.10/site-packages/exceptiongroup/_exceptions.py new file mode 100644 index 0000000..ebdd172 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup/_exceptions.py @@ -0,0 +1,280 @@ +from __future__ import annotations + +from collections.abc import Callable, Sequence +from functools import partial +from inspect import getmro, isclass +from typing import TYPE_CHECKING, Any, Generic, Type, TypeVar, cast, overload + +if TYPE_CHECKING: + from typing import Self + +_BaseExceptionT_co = TypeVar("_BaseExceptionT_co", bound=BaseException, covariant=True) +_BaseExceptionT = TypeVar("_BaseExceptionT", bound=BaseException) +_ExceptionT_co = TypeVar("_ExceptionT_co", bound=Exception, covariant=True) +_ExceptionT = TypeVar("_ExceptionT", bound=Exception) + + +def check_direct_subclass( + exc: BaseException, parents: tuple[type[BaseException]] +) -> bool: + for cls in getmro(exc.__class__)[:-1]: + if cls in parents: + return True + + return False + + +def get_condition_filter( + condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co], bool] +) -> Callable[[_BaseExceptionT_co], bool]: + if isclass(condition) and issubclass( + cast(Type[BaseException], condition), BaseException + ): + return partial(check_direct_subclass, parents=(condition,)) + elif isinstance(condition, tuple): + if all(isclass(x) and issubclass(x, BaseException) for x in condition): + return partial(check_direct_subclass, parents=condition) + elif callable(condition): + return cast("Callable[[BaseException], bool]", condition) + + raise TypeError("expected a function, exception type or tuple of exception types") + + +class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]): + """A combination of multiple unrelated exceptions.""" + + def __new__( + cls, __message: str, __exceptions: Sequence[_BaseExceptionT_co] + ) -> Self: + if not isinstance(__message, str): + raise TypeError(f"argument 1 must be str, not {type(__message)}") + if not isinstance(__exceptions, Sequence): + raise TypeError("second argument (exceptions) must be a sequence") + if not __exceptions: + raise ValueError( + "second argument (exceptions) must be a non-empty sequence" + ) + + for i, exc in enumerate(__exceptions): + if not isinstance(exc, BaseException): + raise ValueError( + f"Item {i} of second argument (exceptions) is not an " f"exception" + ) + + if cls is BaseExceptionGroup: + if all(isinstance(exc, Exception) for exc in __exceptions): + cls = ExceptionGroup + + return super().__new__(cls, __message, __exceptions) + + def __init__( + self, __message: str, __exceptions: Sequence[_BaseExceptionT_co], *args: Any + ): + super().__init__(__message, __exceptions, *args) + self._message = __message + self._exceptions = __exceptions + + def add_note(self, note: str) -> None: + if not isinstance(note, str): + raise TypeError( + f"Expected a string, got note={note!r} (type {type(note).__name__})" + ) + + if not hasattr(self, "__notes__"): + self.__notes__: list[str] = [] + + self.__notes__.append(note) + + @property + def message(self) -> str: + return self._message + + @property + def exceptions( + self, + ) -> tuple[_BaseExceptionT_co | BaseExceptionGroup[_BaseExceptionT_co], ...]: + return tuple(self._exceptions) + + @overload + def subgroup( + self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] + ) -> BaseExceptionGroup[_BaseExceptionT] | None: + ... + + @overload + def subgroup( + self: Self, __condition: Callable[[_BaseExceptionT_co], bool] + ) -> Self | None: + ... + + def subgroup( + self: Self, + __condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co], bool], + ) -> BaseExceptionGroup[_BaseExceptionT] | Self | None: + condition = get_condition_filter(__condition) + modified = False + if condition(self): + return self + + exceptions: list[BaseException] = [] + for exc in self.exceptions: + if isinstance(exc, BaseExceptionGroup): + subgroup = exc.subgroup(__condition) + if subgroup is not None: + exceptions.append(subgroup) + + if subgroup is not exc: + modified = True + elif condition(exc): + exceptions.append(exc) + else: + modified = True + + if not modified: + return self + elif exceptions: + group = self.derive(exceptions) + group.__cause__ = self.__cause__ + group.__context__ = self.__context__ + group.__traceback__ = self.__traceback__ + return group + else: + return None + + @overload + def split( + self: Self, + __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...], + ) -> tuple[BaseExceptionGroup[_BaseExceptionT] | None, Self | None]: + ... + + @overload + def split( + self: Self, __condition: Callable[[_BaseExceptionT_co], bool] + ) -> tuple[Self | None, Self | None]: + ... + + def split( + self: Self, + __condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co], bool], + ) -> tuple[BaseExceptionGroup[_BaseExceptionT] | None, Self | None] | tuple[ + Self | None, Self | None + ]: + condition = get_condition_filter(__condition) + if condition(self): + return self, None + + matching_exceptions: list[BaseException] = [] + nonmatching_exceptions: list[BaseException] = [] + for exc in self.exceptions: + if isinstance(exc, BaseExceptionGroup): + matching, nonmatching = exc.split(condition) + if matching is not None: + matching_exceptions.append(matching) + + if nonmatching is not None: + nonmatching_exceptions.append(nonmatching) + elif condition(exc): + matching_exceptions.append(exc) + else: + nonmatching_exceptions.append(exc) + + matching_group: Self | None = None + if matching_exceptions: + matching_group = self.derive(matching_exceptions) + matching_group.__cause__ = self.__cause__ + matching_group.__context__ = self.__context__ + matching_group.__traceback__ = self.__traceback__ + + nonmatching_group: Self | None = None + if nonmatching_exceptions: + nonmatching_group = self.derive(nonmatching_exceptions) + nonmatching_group.__cause__ = self.__cause__ + nonmatching_group.__context__ = self.__context__ + nonmatching_group.__traceback__ = self.__traceback__ + + return matching_group, nonmatching_group + + def derive(self: Self, __excs: Sequence[_BaseExceptionT_co]) -> Self: + eg = BaseExceptionGroup(self.message, __excs) + if hasattr(self, "__notes__"): + # Create a new list so that add_note() only affects one exceptiongroup + eg.__notes__ = list(self.__notes__) + + return eg + + def __str__(self) -> str: + suffix = "" if len(self._exceptions) == 1 else "s" + return f"{self.message} ({len(self._exceptions)} sub-exception{suffix})" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.message!r}, {self._exceptions!r})" + + +class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): + def __new__(cls, __message: str, __exceptions: Sequence[_ExceptionT_co]) -> Self: + instance: ExceptionGroup[_ExceptionT_co] = super().__new__( + cls, __message, __exceptions + ) + if cls is ExceptionGroup: + for exc in __exceptions: + if not isinstance(exc, Exception): + raise TypeError("Cannot nest BaseExceptions in an ExceptionGroup") + + return instance + + if TYPE_CHECKING: + + @property + def exceptions( + self, + ) -> tuple[_ExceptionT_co | ExceptionGroup[_ExceptionT_co], ...]: + ... + + @overload # type: ignore[override] + def subgroup( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> ExceptionGroup[_ExceptionT] | None: + ... + + @overload + def subgroup( + self: Self, __condition: Callable[[_ExceptionT_co], bool] + ) -> Self | None: + ... + + def subgroup( + self: Self, + __condition: type[_ExceptionT] + | tuple[type[_ExceptionT], ...] + | Callable[[_ExceptionT_co], bool], + ) -> ExceptionGroup[_ExceptionT] | Self | None: + return super().subgroup(__condition) + + @overload # type: ignore[override] + def split( + self: Self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> tuple[ExceptionGroup[_ExceptionT] | None, Self | None]: + ... + + @overload + def split( + self: Self, __condition: Callable[[_ExceptionT_co], bool] + ) -> tuple[Self | None, Self | None]: + ... + + def split( + self: Self, + __condition: type[_ExceptionT] + | tuple[type[_ExceptionT], ...] + | Callable[[_ExceptionT_co], bool], + ) -> tuple[ExceptionGroup[_ExceptionT] | None, Self | None] | tuple[ + Self | None, Self | None + ]: + return super().split(__condition) diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/_formatting.py b/axios-example/lib/python3.10/site-packages/exceptiongroup/_formatting.py new file mode 100644 index 0000000..4ff269b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup/_formatting.py @@ -0,0 +1,554 @@ +# traceback_exception_init() adapted from trio +# +# _ExceptionPrintContext and traceback_exception_format() copied from the standard +# library +from __future__ import annotations + +import collections.abc +import sys +import textwrap +import traceback +from functools import singledispatch +from types import TracebackType +from typing import Any, List, Optional + +from ._exceptions import BaseExceptionGroup + +max_group_width = 15 +max_group_depth = 10 +_cause_message = ( + "\nThe above exception was the direct cause of the following exception:\n\n" +) + +_context_message = ( + "\nDuring handling of the above exception, another exception occurred:\n\n" +) + + +def _format_final_exc_line(etype, value): + valuestr = _safe_string(value, "exception") + if value is None or not valuestr: + line = f"{etype}\n" + else: + line = f"{etype}: {valuestr}\n" + + return line + + +def _safe_string(value, what, func=str): + try: + return func(value) + except BaseException: + return f"<{what} {func.__name__}() failed>" + + +class _ExceptionPrintContext: + def __init__(self): + self.seen = set() + self.exception_group_depth = 0 + self.need_close = False + + def indent(self): + return " " * (2 * self.exception_group_depth) + + def emit(self, text_gen, margin_char=None): + if margin_char is None: + margin_char = "|" + indent_str = self.indent() + if self.exception_group_depth: + indent_str += margin_char + " " + + if isinstance(text_gen, str): + yield textwrap.indent(text_gen, indent_str, lambda line: True) + else: + for text in text_gen: + yield textwrap.indent(text, indent_str, lambda line: True) + + +def exceptiongroup_excepthook( + etype: type[BaseException], value: BaseException, tb: TracebackType | None +) -> None: + sys.stderr.write("".join(traceback.format_exception(etype, value, tb))) + + +class PatchedTracebackException(traceback.TracebackException): + def __init__( + self, + exc_type: type[BaseException], + exc_value: BaseException, + exc_traceback: TracebackType | None, + *, + limit: int | None = None, + lookup_lines: bool = True, + capture_locals: bool = False, + compact: bool = False, + _seen: set[int] | None = None, + ) -> None: + kwargs: dict[str, Any] = {} + if sys.version_info >= (3, 10): + kwargs["compact"] = compact + + is_recursive_call = _seen is not None + if _seen is None: + _seen = set() + _seen.add(id(exc_value)) + + self.stack = traceback.StackSummary.extract( + traceback.walk_tb(exc_traceback), + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + ) + self.exc_type = exc_type + # Capture now to permit freeing resources: only complication is in the + # unofficial API _format_final_exc_line + self._str = _safe_string(exc_value, "exception") + self.__notes__ = getattr(exc_value, "__notes__", None) + + if exc_type and issubclass(exc_type, SyntaxError): + # Handle SyntaxError's specially + self.filename = exc_value.filename + lno = exc_value.lineno + self.lineno = str(lno) if lno is not None else None + self.text = exc_value.text + self.offset = exc_value.offset + self.msg = exc_value.msg + if sys.version_info >= (3, 10): + end_lno = exc_value.end_lineno + self.end_lineno = str(end_lno) if end_lno is not None else None + self.end_offset = exc_value.end_offset + elif ( + exc_type + and issubclass(exc_type, (NameError, AttributeError)) + and getattr(exc_value, "name", None) is not None + ): + suggestion = _compute_suggestion_error(exc_value, exc_traceback) + if suggestion: + self._str += f". Did you mean: '{suggestion}'?" + + if lookup_lines: + # Force all lines in the stack to be loaded + for frame in self.stack: + frame.line + + self.__suppress_context__ = ( + exc_value.__suppress_context__ if exc_value is not None else False + ) + + # Convert __cause__ and __context__ to `TracebackExceptions`s, use a + # queue to avoid recursion (only the top-level call gets _seen == None) + if not is_recursive_call: + queue = [(self, exc_value)] + while queue: + te, e = queue.pop() + + if e and e.__cause__ is not None and id(e.__cause__) not in _seen: + cause = PatchedTracebackException( + type(e.__cause__), + e.__cause__, + e.__cause__.__traceback__, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + else: + cause = None + + if compact: + need_context = ( + cause is None and e is not None and not e.__suppress_context__ + ) + else: + need_context = True + if ( + e + and e.__context__ is not None + and need_context + and id(e.__context__) not in _seen + ): + context = PatchedTracebackException( + type(e.__context__), + e.__context__, + e.__context__.__traceback__, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + else: + context = None + + # Capture each of the exceptions in the ExceptionGroup along with each + # of their causes and contexts + if e and isinstance(e, BaseExceptionGroup): + exceptions = [] + for exc in e.exceptions: + texc = PatchedTracebackException( + type(exc), + exc, + exc.__traceback__, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + exceptions.append(texc) + else: + exceptions = None + + te.__cause__ = cause + te.__context__ = context + te.exceptions = exceptions + if cause: + queue.append((te.__cause__, e.__cause__)) + if context: + queue.append((te.__context__, e.__context__)) + if exceptions: + queue.extend(zip(te.exceptions, e.exceptions)) + + def format(self, *, chain=True, _ctx=None): + if _ctx is None: + _ctx = _ExceptionPrintContext() + + output = [] + exc = self + if chain: + while exc: + if exc.__cause__ is not None: + chained_msg = _cause_message + chained_exc = exc.__cause__ + elif exc.__context__ is not None and not exc.__suppress_context__: + chained_msg = _context_message + chained_exc = exc.__context__ + else: + chained_msg = None + chained_exc = None + + output.append((chained_msg, exc)) + exc = chained_exc + else: + output.append((None, exc)) + + for msg, exc in reversed(output): + if msg is not None: + yield from _ctx.emit(msg) + if exc.exceptions is None: + if exc.stack: + yield from _ctx.emit("Traceback (most recent call last):\n") + yield from _ctx.emit(exc.stack.format()) + yield from _ctx.emit(exc.format_exception_only()) + elif _ctx.exception_group_depth > max_group_depth: + # exception group, but depth exceeds limit + yield from _ctx.emit(f"... (max_group_depth is {max_group_depth})\n") + else: + # format exception group + is_toplevel = _ctx.exception_group_depth == 0 + if is_toplevel: + _ctx.exception_group_depth += 1 + + if exc.stack: + yield from _ctx.emit( + "Exception Group Traceback (most recent call last):\n", + margin_char="+" if is_toplevel else None, + ) + yield from _ctx.emit(exc.stack.format()) + + yield from _ctx.emit(exc.format_exception_only()) + num_excs = len(exc.exceptions) + if num_excs <= max_group_width: + n = num_excs + else: + n = max_group_width + 1 + _ctx.need_close = False + for i in range(n): + last_exc = i == n - 1 + if last_exc: + # The closing frame may be added by a recursive call + _ctx.need_close = True + + if max_group_width is not None: + truncated = i >= max_group_width + else: + truncated = False + title = f"{i + 1}" if not truncated else "..." + yield ( + _ctx.indent() + + ("+-" if i == 0 else " ") + + f"+---------------- {title} ----------------\n" + ) + _ctx.exception_group_depth += 1 + if not truncated: + yield from exc.exceptions[i].format(chain=chain, _ctx=_ctx) + else: + remaining = num_excs - max_group_width + plural = "s" if remaining > 1 else "" + yield from _ctx.emit( + f"and {remaining} more exception{plural}\n" + ) + + if last_exc and _ctx.need_close: + yield _ctx.indent() + "+------------------------------------\n" + _ctx.need_close = False + _ctx.exception_group_depth -= 1 + + if is_toplevel: + assert _ctx.exception_group_depth == 1 + _ctx.exception_group_depth = 0 + + def format_exception_only(self): + """Format the exception part of the traceback. + The return value is a generator of strings, each ending in a newline. + Normally, the generator emits a single string; however, for + SyntaxError exceptions, it emits several lines that (when + printed) display detailed information about where the syntax + error occurred. + The message indicating which exception occurred is always the last + string in the output. + """ + if self.exc_type is None: + yield traceback._format_final_exc_line(None, self._str) + return + + stype = self.exc_type.__qualname__ + smod = self.exc_type.__module__ + if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" + stype = smod + "." + stype + + if not issubclass(self.exc_type, SyntaxError): + yield _format_final_exc_line(stype, self._str) + elif traceback_exception_format_syntax_error is not None: + yield from traceback_exception_format_syntax_error(self, stype) + else: + yield from traceback_exception_original_format_exception_only(self) + + if isinstance(self.__notes__, collections.abc.Sequence): + for note in self.__notes__: + note = _safe_string(note, "note") + yield from [line + "\n" for line in note.split("\n")] + elif self.__notes__ is not None: + yield _safe_string(self.__notes__, "__notes__", func=repr) + + +traceback_exception_original_format = traceback.TracebackException.format +traceback_exception_original_format_exception_only = ( + traceback.TracebackException.format_exception_only +) +traceback_exception_format_syntax_error = getattr( + traceback.TracebackException, "_format_syntax_error", None +) +if sys.excepthook is sys.__excepthook__: + traceback.TracebackException.__init__ = ( # type: ignore[assignment] + PatchedTracebackException.__init__ + ) + traceback.TracebackException.format = ( # type: ignore[assignment] + PatchedTracebackException.format + ) + traceback.TracebackException.format_exception_only = ( # type: ignore[assignment] + PatchedTracebackException.format_exception_only + ) + sys.excepthook = exceptiongroup_excepthook + + +@singledispatch +def format_exception_only(__exc: BaseException) -> List[str]: + return list( + PatchedTracebackException( + type(__exc), __exc, None, compact=True + ).format_exception_only() + ) + + +@format_exception_only.register +def _(__exc: type, value: BaseException) -> List[str]: + return format_exception_only(value) + + +@singledispatch +def format_exception( + __exc: BaseException, + limit: Optional[int] = None, + chain: bool = True, +) -> List[str]: + return list( + PatchedTracebackException( + type(__exc), __exc, __exc.__traceback__, limit=limit, compact=True + ).format(chain=chain) + ) + + +@format_exception.register +def _( + __exc: type, + value: BaseException, + tb: TracebackType, + limit: Optional[int] = None, + chain: bool = True, +) -> List[str]: + return format_exception(value, limit, chain) + + +@singledispatch +def print_exception( + __exc: BaseException, + limit: Optional[int] = None, + file: Any = None, + chain: bool = True, +) -> None: + if file is None: + file = sys.stderr + + for line in PatchedTracebackException( + type(__exc), __exc, __exc.__traceback__, limit=limit + ).format(chain=chain): + print(line, file=file, end="") + + +@print_exception.register +def _( + __exc: type, + value: BaseException, + tb: TracebackType, + limit: Optional[int] = None, + file: Any = None, + chain: bool = True, +) -> None: + print_exception(value, limit, file, chain) + + +def print_exc( + limit: Optional[int] = None, + file: Any | None = None, + chain: bool = True, +) -> None: + value = sys.exc_info()[1] + print_exception(value, limit, file, chain) + + +# Python levenshtein edit distance code for NameError/AttributeError +# suggestions, backported from 3.12 + +_MAX_CANDIDATE_ITEMS = 750 +_MAX_STRING_SIZE = 40 +_MOVE_COST = 2 +_CASE_COST = 1 +_SENTINEL = object() + + +def _substitution_cost(ch_a, ch_b): + if ch_a == ch_b: + return 0 + if ch_a.lower() == ch_b.lower(): + return _CASE_COST + return _MOVE_COST + + +def _compute_suggestion_error(exc_value, tb): + wrong_name = getattr(exc_value, "name", None) + if wrong_name is None or not isinstance(wrong_name, str): + return None + if isinstance(exc_value, AttributeError): + obj = getattr(exc_value, "obj", _SENTINEL) + if obj is _SENTINEL: + return None + obj = exc_value.obj + try: + d = dir(obj) + except Exception: + return None + else: + assert isinstance(exc_value, NameError) + # find most recent frame + if tb is None: + return None + while tb.tb_next is not None: + tb = tb.tb_next + frame = tb.tb_frame + + d = list(frame.f_locals) + list(frame.f_globals) + list(frame.f_builtins) + if len(d) > _MAX_CANDIDATE_ITEMS: + return None + wrong_name_len = len(wrong_name) + if wrong_name_len > _MAX_STRING_SIZE: + return None + best_distance = wrong_name_len + suggestion = None + for possible_name in d: + if possible_name == wrong_name: + # A missing attribute is "found". Don't suggest it (see GH-88821). + continue + # No more than 1/3 of the involved characters should need changed. + max_distance = (len(possible_name) + wrong_name_len + 3) * _MOVE_COST // 6 + # Don't take matches we've already beaten. + max_distance = min(max_distance, best_distance - 1) + current_distance = _levenshtein_distance( + wrong_name, possible_name, max_distance + ) + if current_distance > max_distance: + continue + if not suggestion or current_distance < best_distance: + suggestion = possible_name + best_distance = current_distance + return suggestion + + +def _levenshtein_distance(a, b, max_cost): + # A Python implementation of Python/suggestions.c:levenshtein_distance. + + # Both strings are the same + if a == b: + return 0 + + # Trim away common affixes + pre = 0 + while a[pre:] and b[pre:] and a[pre] == b[pre]: + pre += 1 + a = a[pre:] + b = b[pre:] + post = 0 + while a[: post or None] and b[: post or None] and a[post - 1] == b[post - 1]: + post -= 1 + a = a[: post or None] + b = b[: post or None] + if not a or not b: + return _MOVE_COST * (len(a) + len(b)) + if len(a) > _MAX_STRING_SIZE or len(b) > _MAX_STRING_SIZE: + return max_cost + 1 + + # Prefer shorter buffer + if len(b) < len(a): + a, b = b, a + + # Quick fail when a match is impossible + if (len(b) - len(a)) * _MOVE_COST > max_cost: + return max_cost + 1 + + # Instead of producing the whole traditional len(a)-by-len(b) + # matrix, we can update just one row in place. + # Initialize the buffer row + row = list(range(_MOVE_COST, _MOVE_COST * (len(a) + 1), _MOVE_COST)) + + result = 0 + for bindex in range(len(b)): + bchar = b[bindex] + distance = result = bindex * _MOVE_COST + minimum = sys.maxsize + for index in range(len(a)): + # 1) Previous distance in this row is cost(b[:b_index], a[:index]) + substitute = distance + _substitution_cost(bchar, a[index]) + # 2) cost(b[:b_index], a[:index+1]) from previous row + distance = row[index] + # 3) existing result is cost(b[:b_index+1], a[index]) + + insert_delete = min(result, distance) + _MOVE_COST + result = min(insert_delete, substitute) + + # cost(b[:b_index+1], a[:index+1]) + row[index] = result + if result < minimum: + minimum = result + if minimum > max_cost: + # Everything in this row is too big, so bail early. + return max_cost + 1 + return result diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/_version.py b/axios-example/lib/python3.10/site-packages/exceptiongroup/_version.py new file mode 100644 index 0000000..a33069f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/exceptiongroup/_version.py @@ -0,0 +1,5 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +__version__ = version = '1.0.4' +__version_tuple__ = version_tuple = (1, 0, 4) diff --git a/axios-example/lib/python3.10/site-packages/exceptiongroup/py.typed b/axios-example/lib/python3.10/site-packages/exceptiongroup/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/flask/__init__.py b/axios-example/lib/python3.10/site-packages/flask/__init__.py new file mode 100644 index 0000000..f684f57 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/__init__.py @@ -0,0 +1,45 @@ +from markupsafe import escape +from markupsafe import Markup +from werkzeug.exceptions import abort as abort +from werkzeug.utils import redirect as redirect + +from . import json as json +from .app import Flask as Flask +from .app import Request as Request +from .app import Response as Response +from .blueprints import Blueprint as Blueprint +from .config import Config as Config +from .ctx import after_this_request as after_this_request +from .ctx import copy_current_request_context as copy_current_request_context +from .ctx import has_app_context as has_app_context +from .ctx import has_request_context as has_request_context +from .globals import _app_ctx_stack as _app_ctx_stack +from .globals import _request_ctx_stack as _request_ctx_stack +from .globals import current_app as current_app +from .globals import g as g +from .globals import request as request +from .globals import session as session +from .helpers import flash as flash +from .helpers import get_flashed_messages as get_flashed_messages +from .helpers import get_template_attribute as get_template_attribute +from .helpers import make_response as make_response +from .helpers import send_file as send_file +from .helpers import send_from_directory as send_from_directory +from .helpers import stream_with_context as stream_with_context +from .helpers import url_for as url_for +from .json import jsonify as jsonify +from .signals import appcontext_popped as appcontext_popped +from .signals import appcontext_pushed as appcontext_pushed +from .signals import appcontext_tearing_down as appcontext_tearing_down +from .signals import before_render_template as before_render_template +from .signals import got_request_exception as got_request_exception +from .signals import message_flashed as message_flashed +from .signals import request_finished as request_finished +from .signals import request_started as request_started +from .signals import request_tearing_down as request_tearing_down +from .signals import signals_available as signals_available +from .signals import template_rendered as template_rendered +from .templating import render_template as render_template +from .templating import render_template_string as render_template_string + +__version__ = "2.1.2" diff --git a/axios-example/lib/python3.10/site-packages/flask/__main__.py b/axios-example/lib/python3.10/site-packages/flask/__main__.py new file mode 100644 index 0000000..4e28416 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/axios-example/lib/python3.10/site-packages/flask/app.py b/axios-example/lib/python3.10/site-packages/flask/app.py new file mode 100644 index 0000000..348bc7f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/app.py @@ -0,0 +1,2095 @@ +import functools +import inspect +import logging +import os +import sys +import typing as t +import weakref +from datetime import timedelta +from itertools import chain +from threading import Lock +from types import TracebackType + +from werkzeug.datastructures import Headers +from werkzeug.datastructures import ImmutableDict +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.exceptions import HTTPException +from werkzeug.exceptions import InternalServerError +from werkzeug.routing import BuildError +from werkzeug.routing import Map +from werkzeug.routing import MapAdapter +from werkzeug.routing import RequestRedirect +from werkzeug.routing import RoutingException +from werkzeug.routing import Rule +from werkzeug.wrappers import Response as BaseResponse + +from . import cli +from . import json +from .config import Config +from .config import ConfigAttribute +from .ctx import _AppCtxGlobals +from .ctx import AppContext +from .ctx import RequestContext +from .globals import _request_ctx_stack +from .globals import g +from .globals import request +from .globals import session +from .helpers import _split_blueprint_path +from .helpers import get_debug_flag +from .helpers import get_env +from .helpers import get_flashed_messages +from .helpers import get_load_dotenv +from .helpers import locked_cached_property +from .helpers import url_for +from .json import jsonify +from .logging import create_logger +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import find_package +from .scaffold import Scaffold +from .scaffold import setupmethod +from .sessions import SecureCookieSessionInterface +from .sessions import SessionInterface +from .signals import appcontext_tearing_down +from .signals import got_request_exception +from .signals import request_finished +from .signals import request_started +from .signals import request_tearing_down +from .templating import DispatchingJinjaLoader +from .templating import Environment +from .typing import BeforeFirstRequestCallable +from .typing import ResponseReturnValue +from .typing import TeardownCallable +from .typing import TemplateFilterCallable +from .typing import TemplateGlobalCallable +from .typing import TemplateTestCallable +from .wrappers import Request +from .wrappers import Response + +if t.TYPE_CHECKING: + import typing_extensions as te + from .blueprints import Blueprint + from .testing import FlaskClient + from .testing import FlaskCliRunner + from .typing import ErrorHandlerCallable + +if sys.version_info >= (3, 8): + iscoroutinefunction = inspect.iscoroutinefunction +else: + + def iscoroutinefunction(func: t.Any) -> bool: + while inspect.ismethod(func): + func = func.__func__ + + while isinstance(func, functools.partial): + func = func.func + + return inspect.iscoroutinefunction(func) + + +def _make_timedelta(value: t.Optional[timedelta]) -> t.Optional[timedelta]: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class Flask(Scaffold): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class = Response + + #: The class that is used for the Jinja environment. + #: + #: .. versionadded:: 0.11 + jinja_environment = Environment + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on unexpected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is now application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + #: The class that is used for the ``config`` attribute of this app. + #: Defaults to :class:`~flask.Config`. + #: + #: Example use cases for a custom class: + #: + #: 1. Default values for certain config options. + #: 2. Access to config values through attributes in addition to keys. + #: + #: .. versionadded:: 0.11 + config_class = Config + + #: The testing flag. Set this to ``True`` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate test helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: ``TESTING`` configuration key. Defaults to ``False``. + testing = ConfigAttribute("TESTING") + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. + secret_key = ConfigAttribute("SECRET_KEY") + + #: The secure cookie uses this for the name of the session cookie. + #: + #: This attribute can also be configured from the config with the + #: ``SESSION_COOKIE_NAME`` configuration key. Defaults to ``'session'`` + session_cookie_name = ConfigAttribute("SESSION_COOKIE_NAME") + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute( + "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta + ) + + #: A :class:`~datetime.timedelta` or number of seconds which is used + #: as the default ``max_age`` for :func:`send_file`. The default is + #: ``None``, which tells the browser to use conditional requests + #: instead of a timed cache. + #: + #: Configured with the :data:`SEND_FILE_MAX_AGE_DEFAULT` + #: configuration key. + #: + #: .. versionchanged:: 2.0 + #: Defaults to ``None`` instead of 12 hours. + send_file_max_age_default = ConfigAttribute( + "SEND_FILE_MAX_AGE_DEFAULT", get_converter=_make_timedelta + ) + + #: Enable this if you want to use the X-Sendfile feature. Keep in + #: mind that the server has to support this. This only affects files + #: sent with the :func:`send_file` method. + #: + #: .. versionadded:: 0.2 + #: + #: This attribute can also be configured from the config with the + #: ``USE_X_SENDFILE`` configuration key. Defaults to ``False``. + use_x_sendfile = ConfigAttribute("USE_X_SENDFILE") + + #: The JSON encoder class to use. Defaults to :class:`~flask.json.JSONEncoder`. + #: + #: .. versionadded:: 0.10 + json_encoder = json.JSONEncoder + + #: The JSON decoder class to use. Defaults to :class:`~flask.json.JSONDecoder`. + #: + #: .. versionadded:: 0.10 + json_decoder = json.JSONDecoder + + #: Options that are passed to the Jinja environment in + #: :meth:`create_jinja_environment`. Changing these options after + #: the environment is created (accessing :attr:`jinja_env`) will + #: have no effect. + #: + #: .. versionchanged:: 1.1.0 + #: This is a ``dict`` instead of an ``ImmutableDict`` to allow + #: easier configuration. + #: + jinja_options: dict = {} + + #: Default configuration parameters. + default_config = ImmutableDict( + { + "ENV": None, + "DEBUG": None, + "TESTING": False, + "PROPAGATE_EXCEPTIONS": None, + "PRESERVE_CONTEXT_ON_EXCEPTION": None, + "SECRET_KEY": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "SERVER_NAME": None, + "APPLICATION_ROOT": "/", + "SESSION_COOKIE_NAME": "session", + "SESSION_COOKIE_DOMAIN": None, + "SESSION_COOKIE_PATH": None, + "SESSION_COOKIE_HTTPONLY": True, + "SESSION_COOKIE_SECURE": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "SEND_FILE_MAX_AGE_DEFAULT": None, + "TRAP_BAD_REQUEST_ERRORS": None, + "TRAP_HTTP_EXCEPTIONS": False, + "EXPLAIN_TEMPLATE_LOADING": False, + "PREFERRED_URL_SCHEME": "http", + "JSON_AS_ASCII": True, + "JSON_SORT_KEYS": True, + "JSONIFY_PRETTYPRINT_REGULAR": False, + "JSONIFY_MIMETYPE": "application/json", + "TEMPLATES_AUTO_RELOAD": None, + "MAX_COOKIE_SIZE": 4093, + } + ) + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: The map object to use for storing the URL rules and routing + #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. + #: + #: .. versionadded:: 1.1.0 + url_map_class = Map + + #: The :meth:`test_client` method creates an instance of this test + #: client class. Defaults to :class:`~flask.testing.FlaskClient`. + #: + #: .. versionadded:: 0.7 + test_client_class: t.Optional[t.Type["FlaskClient"]] = None + + #: The :class:`~click.testing.CliRunner` subclass, by default + #: :class:`~flask.testing.FlaskCliRunner` that is used by + #: :meth:`test_cli_runner`. Its ``__init__`` method should take a + #: Flask app object as the first argument. + #: + #: .. versionadded:: 1.0 + test_cli_runner_class: t.Optional[t.Type["FlaskCliRunner"]] = None + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: t.Optional[str] = None, + static_folder: t.Optional[t.Union[str, os.PathLike]] = "static", + static_host: t.Optional[str] = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: t.Optional[str] = "templates", + instance_path: t.Optional[str] = None, + instance_relative_config: bool = False, + root_path: t.Optional[str] = None, + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: A list of functions that are called when :meth:`url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function registered here + #: is called with `error`, `endpoint` and `values`. If a function + #: returns ``None`` or raises a :exc:`BuildError` the next function is + #: tried. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: t.List[ + t.Callable[[Exception, str, dict], str] + ] = [] + + #: A list of functions that will be called at the beginning of the + #: first request to this instance. To register a function, use the + #: :meth:`before_first_request` decorator. + #: + #: .. versionadded:: 0.8 + self.before_first_request_funcs: t.List[BeforeFirstRequestCallable] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: t.List[TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: t.List[t.Callable[[], t.Dict[str, t.Any]]] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: t.Dict[str, "Blueprint"] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class() + + self.url_map.host_matching = host_matching + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + self._before_request_lock = Lock() + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert ( + bool(static_host) == host_matching + ), "Invalid static_host/host_matching combination" + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def _is_setup_finished(self) -> bool: + return self.debug and self._got_first_request + + @locked_cached_property + def name(self) -> str: # type: ignore + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @property + def propagate_exceptions(self) -> bool: + """Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration + value in case it's set, otherwise a sensible default is returned. + + .. versionadded:: 0.7 + """ + rv = self.config["PROPAGATE_EXCEPTIONS"] + if rv is not None: + return rv + return self.testing or self.debug + + @property + def preserve_context_on_exception(self) -> bool: + """Returns the value of the ``PRESERVE_CONTEXT_ON_EXCEPTION`` + configuration value in case it's set, otherwise a sensible default + is returned. + + .. versionadded:: 0.7 + """ + rv = self.config["PRESERVE_CONTEXT_ON_EXCEPTION"] + if rv is not None: + return rv + return self.debug + + @locked_cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @locked_cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + @property + def got_first_request(self) -> bool: + """This attribute is set to ``True`` if the application started + handling the first request. + + .. versionadded:: 0.8 + """ + return self._got_first_request + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["ENV"] = get_env() + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + @property + def templates_auto_reload(self) -> bool: + """Reload templates when they are changed. Used by + :meth:`create_jinja_environment`. + + This attribute can be configured with :data:`TEMPLATES_AUTO_RELOAD`. If + not set, it will be enabled in debug mode. + + .. versionadded:: 1.0 + This property was added but the underlying config and behavior + already existed. + """ + rv = self.config["TEMPLATES_AUTO_RELOAD"] + return rv if rv is not None else self.debug + + @templates_auto_reload.setter + def templates_auto_reload(self, value: bool) -> None: + self.config["TEMPLATES_AUTO_RELOAD"] = value + + def create_jinja_environment(self) -> Environment: + """Create the Jinja environment based on :attr:`jinja_options` + and the various Jinja-related methods of the app. Changing + :attr:`jinja_options` after this will have no effect. Also adds + Flask-related globals and filters to the environment. + + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + + if "autoescape" not in options: + options["autoescape"] = self.select_jinja_autoescape + + if "auto_reload" not in options: + options["auto_reload"] = self.templates_auto_reload + + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g, + ) + rv.policies["json.dumps_function"] = json.dumps + return rv + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml")) + + def update_template_context(self, context: dict) -> None: + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + names: t.Iterable[t.Optional[str]] = (None,) + + # A template may be rendered outside a request context. + if request: + names = chain(names, reversed(request.blueprints)) + + # The values passed to render_template take precedence. Keep a + # copy to re-apply after all context functions. + orig_ctx = context.copy() + + for name in names: + if name in self.template_context_processors: + for func in self.template_context_processors[name]: + context.update(func()) + + context.update(orig_ctx) + + def make_shell_context(self) -> dict: + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {"app": self, "g": g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + #: What environment the app is running in. Flask and extensions may + #: enable behaviors based on the environment, such as enabling debug + #: mode. This maps to the :data:`ENV` config key. This is set by the + #: :envvar:`FLASK_ENV` environment variable and may not behave as + #: expected if set in code. + #: + #: **Do not enable development when deploying in production.** + #: + #: Default: ``'production'`` + env = ConfigAttribute("ENV") + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start + the development server, an interactive debugger will be shown for + unhandled exceptions, and the server will be reloaded when code + changes. This maps to the :data:`DEBUG` config key. This is + enabled when :attr:`env` is ``'development'`` and is overridden + by the ``FLASK_DEBUG`` environment variable. It may not behave as + expected if set in code. + + **Do not enable debug mode when deploying in production.** + + Default: ``True`` if :attr:`env` is ``'development'``, or + ``False`` otherwise. + """ + return self.config["DEBUG"] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + self.jinja_env.auto_reload = self.templates_auto_reload + + def run( + self, + host: t.Optional[str] = None, + port: t.Optional[int] = None, + debug: t.Optional[bool] = None, + load_dotenv: bool = True, + **options: t.Any, + ) -> None: + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :doc:`/deploying/index` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable + if present. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if present. + :param debug: if given, enable or disable debug mode. See + :attr:`debug`. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param options: the options to be forwarded to the underlying Werkzeug + server. See :func:`werkzeug.serving.run_simple` for more + information. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment + variables from :file:`.env` and :file:`.flaskenv` files. + + If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG` + environment variables will override :attr:`env` and + :attr:`debug`. + + Threaded mode is enabled by default. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` + variable. + """ + # Change this into a no-op if the server is invoked from the + # command line. Have a look at cli.py for more information. + if os.environ.get("FLASK_RUN_FROM_CLI") == "true": + from .debughelpers import explain_ignored_app_run + + explain_ignored_app_run() + return + + if get_load_dotenv(load_dotenv): + cli.load_dotenv() + + # if set, let env vars override previous values + if "FLASK_ENV" in os.environ: + self.env = get_env() + self.debug = get_debug_flag() + elif "FLASK_DEBUG" in os.environ: + self.debug = get_debug_flag() + + # debug passed to method overrides all other sources + if debug is not None: + self.debug = bool(debug) + + server_name = self.config.get("SERVER_NAME") + sn_host = sn_port = None + + if server_name: + sn_host, _, sn_port = server_name.partition(":") + + if not host: + if sn_host: + host = sn_host + else: + host = "127.0.0.1" + + if port or port == 0: + port = int(port) + elif sn_port: + port = int(sn_port) + else: + port = 5000 + + options.setdefault("use_reloader", self.debug) + options.setdefault("use_debugger", self.debug) + options.setdefault("threaded", True) + + cli.show_server_banner(self.env, self.debug, self.name, False) + + from werkzeug.serving import run_simple + + try: + run_simple(t.cast(str, host), port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> "FlaskClient": + """Creates a test client for this application. For information + about unit testing head over to :doc:`/testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from .testing import FlaskClient as cls # type: ignore + return cls( # type: ignore + self, self.response_class, use_cookies=use_cookies, **kwargs + ) + + def test_cli_runner(self, **kwargs: t.Any) -> "FlaskCliRunner": + """Create a CLI runner for testing CLI commands. + See :ref:`testing-cli`. + + Returns an instance of :attr:`test_cli_runner_class`, by default + :class:`~flask.testing.FlaskCliRunner`. The Flask app object is + passed as the first argument. + + .. versionadded:: 1.0 + """ + cls = self.test_cli_runner_class + + if cls is None: + from .testing import FlaskCliRunner as cls # type: ignore + + return cls(self, **kwargs) # type: ignore + + @setupmethod + def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView["Blueprint"]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[t.Callable] = None, + provide_automatic_options: t.Optional[bool] = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods = set(getattr(view_func, "required_methods", ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + if provide_automatic_options is None: + provide_automatic_options = getattr( + view_func, "provide_automatic_options", None + ) + + if provide_automatic_options is None: + if "OPTIONS" not in methods: + provide_automatic_options = True + required_methods.add("OPTIONS") + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule = self.url_rule_class(rule, methods=methods, **options) + rule.provide_automatic_options = provide_automatic_options # type: ignore + + self.url_map.add(rule) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError( + "View function mapping is overwriting an existing" + f" endpoint function: {endpoint}" + ) + self.view_functions[endpoint] = view_func + + @setupmethod + def template_filter( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]: + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable: + self.add_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_filter( + self, f: TemplateFilterCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]: + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: TemplateTestCallable) -> TemplateTestCallable: + self.add_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_test( + self, f: TemplateTestCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]: + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + + def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable: + self.add_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_global( + self, f: TemplateGlobalCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def before_first_request( + self, f: BeforeFirstRequestCallable + ) -> BeforeFirstRequestCallable: + """Registers a function to be run before the first request to this + instance of the application. + + The function will be called without any arguments and its return + value is ignored. + + .. versionadded:: 0.8 + """ + self.before_first_request_funcs.append(f) + return f + + @setupmethod + def teardown_appcontext(self, f: TeardownCallable) -> TeardownCallable: + """Registers a function to be called when the application context + ends. These functions are typically also called when the request + context is popped. + + Example:: + + ctx = app.app_context() + ctx.push() + ... + ctx.pop() + + When ``ctx.pop()`` is executed in the above example, the teardown + functions are called just before the app context moves from the + stack of active contexts. This becomes relevant if you are using + such constructs in tests. + + Since a request context typically also manages an application + context it would also be called when you pop a request context. + + When a teardown function was called because of an unhandled exception + it will be passed an error object. If an :meth:`errorhandler` is + registered, it will handle the exception and the teardown will not + receive it. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def shell_context_processor(self, f: t.Callable) -> t.Callable: + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + def _find_error_handler(self, e: Exception) -> t.Optional["ErrorHandlerCallable"]: + """Return a registered error handler for an exception in this order: + blueprint handler for a specific code, app handler for a specific code, + blueprint handler for an exception class, app handler for an exception + class, or ``None`` if a suitable handler is not found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + names = (*request.blueprints, None) + + for c in (code, None) if code is not None else (None,): + for name in names: + handler_map = self.error_handler_spec[name][c] + + if not handler_map: + continue + + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + + if handler is not None: + return handler + return None + + def handle_http_exception( + self, e: HTTPException + ) -> t.Union[HTTPException, ResponseReturnValue]: + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionchanged:: 1.0.3 + ``RoutingException``, used internally for actions such as + slash redirects during routing, is not passed to error + handlers. + + .. versionchanged:: 1.0 + Exceptions are looked up by code *and* by MRO, so + ``HTTPException`` subclasses can be handled with a catch-all + handler for the base ``HTTPException``. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + # RoutingExceptions are used internally to trigger routing + # actions, such as slash redirects raising RequestRedirect. They + # are not raised or handled in user code. + if isinstance(e, RoutingException): + return e + + handler = self._find_error_handler(e) + if handler is None: + return e + return self.ensure_sync(handler)(e) + + def trap_http_exception(self, e: Exception) -> bool: + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionchanged:: 1.0 + Bad request errors are not trapped by default in debug mode. + + .. versionadded:: 0.8 + """ + if self.config["TRAP_HTTP_EXCEPTIONS"]: + return True + + trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] + + # if unset, trap key errors in debug mode + if ( + trap_bad_request is None + and self.debug + and isinstance(e, BadRequestKeyError) + ): + return True + + if trap_bad_request: + return isinstance(e, BadRequest) + + return False + + def handle_user_exception( + self, e: Exception + ) -> t.Union[HTTPException, ResponseReturnValue]: + """This method is called whenever an exception occurs that + should be handled. A special case is :class:`~werkzeug + .exceptions.HTTPException` which is forwarded to the + :meth:`handle_http_exception` method. This function will either + return a response value or reraise the exception with the same + traceback. + + .. versionchanged:: 1.0 + Key errors raised from request data like ``form`` show the + bad key in debug mode rather than a generic bad request + message. + + .. versionadded:: 0.7 + """ + if isinstance(e, BadRequestKeyError) and ( + self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] + ): + e.show_exception = True + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e) + + if handler is None: + raise + + return self.ensure_sync(handler)(e) + + def handle_exception(self, e: Exception) -> Response: + """Handle an exception that did not have an error handler + associated with it, or that was raised from an error handler. + This always causes a 500 ``InternalServerError``. + + Always sends the :data:`got_request_exception` signal. + + If :attr:`propagate_exceptions` is ``True``, such as in debug + mode, the error will be re-raised so that the debugger can + display it. Otherwise, the original exception is logged, and + an :exc:`~werkzeug.exceptions.InternalServerError` is returned. + + If an error handler is registered for ``InternalServerError`` or + ``500``, it will be used. For consistency, the handler will + always receive the ``InternalServerError``. The original + unhandled exception is available as ``e.original_exception``. + + .. versionchanged:: 1.1.0 + Always passes the ``InternalServerError`` instance to the + handler, setting ``original_exception`` to the unhandled + error. + + .. versionchanged:: 1.1.0 + ``after_request`` functions and other finalization is done + even for the default 500 response when there is no handler. + + .. versionadded:: 0.3 + """ + exc_info = sys.exc_info() + got_request_exception.send(self, exception=e) + + if self.propagate_exceptions: + # Re-raise if called with an active exception, otherwise + # raise the passed in exception. + if exc_info[1] is e: + raise + + raise e + + self.log_exception(exc_info) + server_error: t.Union[InternalServerError, ResponseReturnValue] + server_error = InternalServerError(original_exception=e) + handler = self._find_error_handler(server_error) + + if handler is not None: + server_error = self.ensure_sync(handler)(server_error) + + return self.finalize_request(server_error, from_error_handler=True) + + def log_exception( + self, + exc_info: t.Union[ + t.Tuple[type, BaseException, TracebackType], t.Tuple[None, None, None] + ], + ) -> None: + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error( + f"Exception on {request.path} [{request.method}]", exc_info=exc_info + ) + + def raise_routing_exception(self, request: Request) -> "te.NoReturn": + """Intercept routing exceptions and possibly do something else. + + In debug mode, intercept a routing redirect and replace it with + an error if the body will be discarded. + + With modern Werkzeug this shouldn't occur, since it now uses a + 308 status which tells the browser to resend the method and + body. + + .. versionchanged:: 2.1 + Don't intercept 307 and 308 redirects. + + :meta private: + :internal: + """ + if ( + not self.debug + or not isinstance(request.routing_exception, RequestRedirect) + or request.routing_exception.code in {307, 308} + or request.method in {"GET", "HEAD", "OPTIONS"} + ): + raise request.routing_exception # type: ignore + + from .debughelpers import FormDataRoutingRedirect + + raise FormDataRoutingRedirect(request) + + def dispatch_request(self) -> ResponseReturnValue: + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = _request_ctx_stack.top.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule = req.url_rule + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if ( + getattr(rule, "provide_automatic_options", False) + and req.method == "OPTIONS" + ): + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) + + def full_dispatch_request(self) -> Response: + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self.try_trigger_before_first_request_functions() + try: + request_started.send(self) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request( + self, + rv: t.Union[ResponseReturnValue, HTTPException], + from_error_handler: bool = False, + ) -> Response: + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send(self, response=response) + except Exception: + if not from_error_handler: + raise + self.logger.exception( + "Request finalizing failed with an error while handling an error" + ) + return response + + def try_trigger_before_first_request_functions(self) -> None: + """Called before each request and will ensure that it triggers + the :attr:`before_first_request_funcs` and only exactly once per + application instance (which means process usually). + + :internal: + """ + if self._got_first_request: + return + with self._before_request_lock: + if self._got_first_request: + return + for func in self.before_first_request_funcs: + self.ensure_sync(func)() + self._got_first_request = True + + def make_default_options_response(self) -> Response: + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = _request_ctx_stack.top.url_adapter + methods = adapter.allowed_methods() + rv = self.response_class() + rv.allow.update(methods) + return rv + + def should_ignore_error(self, error: t.Optional[BaseException]) -> bool: + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def ensure_sync(self, func: t.Callable) -> t.Callable: + """Ensure that the function is synchronous for WSGI workers. + Plain ``def`` functions are returned as-is. ``async def`` + functions are wrapped to run and wait for the response. + + Override this method to change how the app runs async views. + + .. versionadded:: 2.0 + """ + if iscoroutinefunction(func): + return self.async_to_sync(func) + + return func + + def async_to_sync( + self, func: t.Callable[..., t.Coroutine] + ) -> t.Callable[..., t.Any]: + """Return a sync function that will run the coroutine function. + + .. code-block:: python + + result = app.async_to_sync(func)(*args, **kwargs) + + Override this method to change how the app converts async code + to be synchronously callable. + + .. versionadded:: 2.0 + """ + try: + from asgiref.sync import async_to_sync as asgiref_async_to_sync + except ImportError: + raise RuntimeError( + "Install Flask with the 'async' extra in order to use async views." + ) from None + + return asgiref_async_to_sync(func) + + def make_response(self, rv: ResponseReturnValue) -> Response: + """Convert the return value from a view function to an instance of + :attr:`response_class`. + + :param rv: the return value from the view function. The view function + must return a response. Returning ``None``, or the view ending + without returning, is not allowed. The following types are allowed + for ``view_rv``: + + ``str`` + A response object is created with the string encoded to UTF-8 + as the body. + + ``bytes`` + A response object is created with the bytes as the body. + + ``dict`` + A dictionary that will be jsonify'd before being returned. + + ``tuple`` + Either ``(body, status, headers)``, ``(body, status)``, or + ``(body, headers)``, where ``body`` is any of the other types + allowed here, ``status`` is a string or an integer, and + ``headers`` is a dictionary or a list of ``(key, value)`` + tuples. If ``body`` is a :attr:`response_class` instance, + ``status`` overwrites the exiting value and ``headers`` are + extended. + + :attr:`response_class` + The object is returned unchanged. + + other :class:`~werkzeug.wrappers.Response` class + The object is coerced to :attr:`response_class`. + + :func:`callable` + The function is called as a WSGI application. The result is + used to create a response object. + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + + status = headers = None + + # unpack tuple returns + if isinstance(rv, tuple): + len_rv = len(rv) + + # a 3-tuple is unpacked directly + if len_rv == 3: + rv, status, headers = rv # type: ignore[misc] + # decide if a 2-tuple has status or headers + elif len_rv == 2: + if isinstance(rv[1], (Headers, dict, tuple, list)): + rv, headers = rv + else: + rv, status = rv # type: ignore[misc] + # other sized tuples are not allowed + else: + raise TypeError( + "The view function did not return a valid response tuple." + " The tuple must have the form (body, status, headers)," + " (body, status), or (body, headers)." + ) + + # the body must not be None + if rv is None: + raise TypeError( + f"The view function for {request.endpoint!r} did not" + " return a valid response. The function either returned" + " None or ended without a return statement." + ) + + # make sure the body is an instance of the response class + if not isinstance(rv, self.response_class): + if isinstance(rv, (str, bytes, bytearray)): + # let the response class set the status and headers instead of + # waiting to do it manually, so that the class can handle any + # special logic + rv = self.response_class( + rv, + status=status, + headers=headers, # type: ignore[arg-type] + ) + status = headers = None + elif isinstance(rv, dict): + rv = jsonify(rv) + elif isinstance(rv, BaseResponse) or callable(rv): + # evaluate a WSGI callable, or coerce a different response + # class to the correct type + try: + rv = self.response_class.force_type(rv, request.environ) # type: ignore # noqa: B950 + except TypeError as e: + raise TypeError( + f"{e}\nThe view function did not return a valid" + " response. The return type must be a string," + " dict, tuple, Response instance, or WSGI" + f" callable, but it was a {type(rv).__name__}." + ).with_traceback(sys.exc_info()[2]) from None + else: + raise TypeError( + "The view function did not return a valid" + " response. The return type must be a string," + " dict, tuple, Response instance, or WSGI" + f" callable, but it was a {type(rv).__name__}." + ) + + rv = t.cast(Response, rv) + # prefer the status if it was provided + if status is not None: + if isinstance(status, (str, bytes, bytearray)): + rv.status = status + else: + rv.status_code = status + + # extend existing headers with provided headers + if headers: + rv.headers.update(headers) # type: ignore[arg-type] + + return rv + + def create_url_adapter( + self, request: t.Optional[Request] + ) -> t.Optional[MapAdapter]: + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set + up so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + """ + if request is not None: + # If subdomain matching is disabled (the default), use the + # default subdomain in all cases. This should be the default + # in Werkzeug but it currently does not have that feature. + if not self.subdomain_matching: + subdomain = self.url_map.default_subdomain or None + else: + subdomain = None + + return self.url_map.bind_to_environ( + request.environ, + server_name=self.config["SERVER_NAME"], + subdomain=subdomain, + ) + # We need at the very least the server name to be set for this + # to work. + if self.config["SERVER_NAME"] is not None: + return self.url_map.bind( + self.config["SERVER_NAME"], + script_name=self.config["APPLICATION_ROOT"], + url_scheme=self.config["PREFERRED_URL_SCHEME"], + ) + + return None + + def inject_url_defaults(self, endpoint: str, values: dict) -> None: + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + names: t.Iterable[t.Optional[str]] = (None,) + + # url_for may be called outside a request context, parse the + # passed endpoint instead of using request.blueprints. + if "." in endpoint: + names = chain( + names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) + ) + + for name in names: + if name in self.url_default_functions: + for func in self.url_default_functions[name]: + func(endpoint, values) + + def handle_url_build_error( + self, error: Exception, endpoint: str, values: dict + ) -> str: + """Handle :class:`~werkzeug.routing.BuildError` on + :meth:`url_for`. + """ + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + except BuildError as e: + # make error available outside except block + error = e + else: + if rv is not None: + return rv + + # Re-raise if called with an active exception, otherwise raise + # the passed in exception. + if error is sys.exc_info()[1]: + raise + + raise error + + def preprocess_request(self) -> t.Optional[ResponseReturnValue]: + """Called before the request is dispatched. Calls + :attr:`url_value_preprocessors` registered with the app and the + current blueprint (if any). Then calls :attr:`before_request_funcs` + registered with the app and the blueprint. + + If any :meth:`before_request` handler returns a non-None value, the + value is handled as if it was the return value from the view, and + further request handling is stopped. + """ + names = (None, *reversed(request.blueprints)) + + for name in names: + if name in self.url_value_preprocessors: + for url_func in self.url_value_preprocessors[name]: + url_func(request.endpoint, request.view_args) + + for name in names: + if name in self.before_request_funcs: + for before_func in self.before_request_funcs[name]: + rv = self.ensure_sync(before_func)() + + if rv is not None: + return rv + + return None + + def process_response(self, response: Response) -> Response: + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = _request_ctx_stack.top + + for func in ctx._after_request_functions: + response = self.ensure_sync(func)(response) + + for name in chain(request.blueprints, (None,)): + if name in self.after_request_funcs: + for func in reversed(self.after_request_funcs[name]): + response = self.ensure_sync(func)(response) + + if not self.session_interface.is_null_session(ctx.session): + self.session_interface.save_session(self, ctx.session, response) + + return response + + def do_teardown_request( + self, exc: t.Optional[BaseException] = _sentinel # type: ignore + ) -> None: + """Called after the request is dispatched and the response is + returned, right before the request context is popped. + + This calls all functions decorated with + :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` + if a blueprint handled the request. Finally, the + :data:`request_tearing_down` signal is sent. + + This is called by + :meth:`RequestContext.pop() `, + which may be delayed during testing to maintain access to + resources. + + :param exc: An unhandled exception raised while dispatching the + request. Detected from the current exception information if + not passed. Passed to each teardown function. + + .. versionchanged:: 0.9 + Added the ``exc`` argument. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for name in chain(request.blueprints, (None,)): + if name in self.teardown_request_funcs: + for func in reversed(self.teardown_request_funcs[name]): + self.ensure_sync(func)(exc) + + request_tearing_down.send(self, exc=exc) + + def do_teardown_appcontext( + self, exc: t.Optional[BaseException] = _sentinel # type: ignore + ) -> None: + """Called right before the application context is popped. + + When handling a request, the application context is popped + after the request context. See :meth:`do_teardown_request`. + + This calls all functions decorated with + :meth:`teardown_appcontext`. Then the + :data:`appcontext_tearing_down` signal is sent. + + This is called by + :meth:`AppContext.pop() `. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for func in reversed(self.teardown_appcontext_funcs): + self.ensure_sync(func)(exc) + + appcontext_tearing_down.send(self, exc=exc) + + def app_context(self) -> AppContext: + """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` + block to push the context, which will make :data:`current_app` + point at this application. + + An application context is automatically pushed by + :meth:`RequestContext.push() ` + when handling a request, and when running a CLI command. Use + this to manually create a context outside of these situations. + + :: + + with app.app_context(): + init_db() + + See :doc:`/appcontext`. + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ: dict) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` representing a + WSGI environment. Use a ``with`` block to push the context, + which will make :data:`request` point at this request. + + See :doc:`/reqcontext`. + + Typically you should not call this from your own code. A request + context is automatically pushed by the :meth:`wsgi_app` when + handling a request. Use :meth:`test_request_context` to create + an environment and context instead of this method. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` for a WSGI + environment created from the given values. This is mostly useful + during testing, where you may want to run a function that uses + request data without dispatching a full request. + + See :doc:`/reqcontext`. + + Use a ``with`` block to push the context, which will make + :data:`request` point at the request for the created + environment. :: + + with test_request_context(...): + generate_report() + + When using the shell, it may be easier to push and pop the + context manually to avoid indentation. :: + + ctx = app.test_request_context(...) + ctx.push() + ... + ctx.pop() + + Takes the same arguments as Werkzeug's + :class:`~werkzeug.test.EnvironBuilder`, with some defaults from + the application. See the linked Werkzeug docs for most of the + available arguments. Flask-specific behavior is listed here. + + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to + :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param data: The request body, either as a string or a dict of + form keys and values. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + from .testing import EnvironBuilder + + builder = EnvironBuilder(self, *args, **kwargs) + + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any: + """The actual WSGI application. This is not implemented in + :meth:`__call__` so that middlewares can be applied without + losing a reference to the app object. Instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + Teardown events for the request and app contexts are called + even if an unhandled error occurs. Other events may not be + called depending on when an error occurs during dispatch. + See :ref:`callbacks-and-errors`. + + :param environ: A WSGI environment. + :param start_response: A callable accepting a status code, + a list of headers, and an optional exception context to + start the response. + """ + ctx = self.request_context(environ) + error: t.Optional[BaseException] = None + try: + try: + ctx.push() + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: # noqa: B001 + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if self.should_ignore_error(error): + error = None + ctx.auto_pop(error) + + def __call__(self, environ: dict, start_response: t.Callable) -> t.Any: + """The WSGI server calls the Flask application object as the + WSGI application. This calls :meth:`wsgi_app`, which can be + wrapped to apply middleware. + """ + return self.wsgi_app(environ, start_response) diff --git a/axios-example/lib/python3.10/site-packages/flask/blueprints.py b/axios-example/lib/python3.10/site-packages/flask/blueprints.py new file mode 100644 index 0000000..5d3b4e2 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/blueprints.py @@ -0,0 +1,597 @@ +import os +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import Scaffold +from .typing import AfterRequestCallable +from .typing import BeforeFirstRequestCallable +from .typing import BeforeRequestCallable +from .typing import TeardownCallable +from .typing import TemplateContextProcessorCallable +from .typing import TemplateFilterCallable +from .typing import TemplateGlobalCallable +from .typing import TemplateTestCallable +from .typing import URLDefaultCallable +from .typing import URLValuePreprocessorCallable + +if t.TYPE_CHECKING: + from .app import Flask + from .typing import ErrorHandlerCallable + +DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable] + + +class BlueprintSetupState: + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__( + self, + blueprint: "Blueprint", + app: "Flask", + options: t.Any, + first_registration: bool, + ) -> None: + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get("subdomain") + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get("url_prefix") + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + self.name = self.options.get("name", blueprint.name) + self.name_prefix = self.options.get("name_prefix", "") + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get("url_defaults", ())) + + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[t.Callable] = None, + **options: t.Any, + ) -> None: + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix is not None: + if rule: + rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) + else: + rule = self.url_prefix + options.setdefault("subdomain", self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + defaults = self.url_defaults + if "defaults" in options: + defaults = dict(defaults, **options.pop("defaults")) + + self.app.add_url_rule( + rule, + f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), + view_func, + defaults=defaults, + **options, + ) + + +class Blueprint(Scaffold): + """Represents a blueprint, a collection of routes and other + app-related functions that can be registered on a real application + later. + + A blueprint is an object that allows defining application functions + without requiring an application object ahead of time. It uses the + same decorators as :class:`~flask.Flask`, but defers the need for an + application by recording them for later registration. + + Decorating a function with a blueprint creates a deferred function + that is called with :class:`~flask.blueprints.BlueprintSetupState` + when the blueprint is registered on an application. + + See :doc:`/blueprints` for more information. + + :param name: The name of the blueprint. Will be prepended to each + endpoint name. + :param import_name: The name of the blueprint package, usually + ``__name__``. This helps locate the ``root_path`` for the + blueprint. + :param static_folder: A folder with static files that should be + served by the blueprint's static route. The path is relative to + the blueprint's root path. Blueprint static files are disabled + by default. + :param static_url_path: The url to serve static files from. + Defaults to ``static_folder``. If the blueprint does not have + a ``url_prefix``, the app's static route will take precedence, + and the blueprint's static files won't be accessible. + :param template_folder: A folder with templates that should be added + to the app's template search path. The path is relative to the + blueprint's root path. Blueprint templates are disabled by + default. Blueprint templates have a lower precedence than those + in the app's templates folder. + :param url_prefix: A path to prepend to all of the blueprint's URLs, + to make them distinct from the rest of the app's routes. + :param subdomain: A subdomain that blueprint routes will match on by + default. + :param url_defaults: A dict of default values that blueprint routes + will receive by default. + :param root_path: By default, the blueprint will automatically set + this based on ``import_name``. In certain situations this + automatic detection can fail, so the path can be specified + manually instead. + + .. versionchanged:: 1.1.0 + Blueprints have a ``cli`` group to register nested CLI commands. + The ``cli_group`` parameter controls the name of the group under + the ``flask`` command. + + .. versionadded:: 0.7 + """ + + warn_on_modifications = False + _got_registered_once = False + + #: Blueprint local JSON encoder class to use. Set to ``None`` to use + #: the app's :class:`~flask.Flask.json_encoder`. + json_encoder = None + #: Blueprint local JSON decoder class to use. Set to ``None`` to use + #: the app's :class:`~flask.Flask.json_decoder`. + json_decoder = None + + def __init__( + self, + name: str, + import_name: str, + static_folder: t.Optional[t.Union[str, os.PathLike]] = None, + static_url_path: t.Optional[str] = None, + template_folder: t.Optional[str] = None, + url_prefix: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + url_defaults: t.Optional[dict] = None, + root_path: t.Optional[str] = None, + cli_group: t.Optional[str] = _sentinel, # type: ignore + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if "." in name: + raise ValueError("'name' may not contain a dot '.' character.") + + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.deferred_functions: t.List[DeferredSetupFunction] = [] + + if url_defaults is None: + url_defaults = {} + + self.url_values_defaults = url_defaults + self.cli_group = cli_group + self._blueprints: t.List[t.Tuple["Blueprint", dict]] = [] + + def _is_setup_finished(self) -> bool: + return self.warn_on_modifications and self._got_registered_once + + def record(self, func: t.Callable) -> None: + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + if self._got_registered_once and self.warn_on_modifications: + from warnings import warn + + warn( + Warning( + "The blueprint was already registered once but is" + " getting modified now. These changes will not show" + " up." + ) + ) + self.deferred_functions.append(func) + + def record_once(self, func: t.Callable) -> None: + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + + def wrapper(state: BlueprintSetupState) -> None: + if state.first_registration: + func(state) + + return self.record(update_wrapper(wrapper, func)) + + def make_setup_state( + self, app: "Flask", options: dict, first_registration: bool = False + ) -> BlueprintSetupState: + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on this blueprint. Keyword + arguments passed to this method will override the defaults set + on the blueprint. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 2.0 + """ + if blueprint is self: + raise ValueError("Cannot register a blueprint on itself") + self._blueprints.append((blueprint, options)) + + def register(self, app: "Flask", options: dict) -> None: + """Called by :meth:`Flask.register_blueprint` to register all + views and callbacks registered on the blueprint with the + application. Creates a :class:`.BlueprintSetupState` and calls + each :meth:`record` callback with it. + + :param app: The application this blueprint is being registered + with. + :param options: Keyword arguments forwarded from + :meth:`~Flask.register_blueprint`. + + .. versionchanged:: 2.0.1 + Nested blueprints are registered with their dotted name. + This allows different blueprints with the same name to be + nested at different locations. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionchanged:: 2.0.1 + Registering the same blueprint with the same name multiple + times is deprecated and will become an error in Flask 2.1. + """ + name_prefix = options.get("name_prefix", "") + self_name = options.get("name", self.name) + name = f"{name_prefix}.{self_name}".lstrip(".") + + if name in app.blueprints: + bp_desc = "this" if app.blueprints[name] is self else "a different" + existing_at = f" '{name}'" if self_name != name else "" + + raise ValueError( + f"The name '{self_name}' is already registered for" + f" {bp_desc} blueprint{existing_at}. Use 'name=' to" + f" provide a unique name." + ) + + first_bp_registration = not any(bp is self for bp in app.blueprints.values()) + first_name_registration = name not in app.blueprints + + app.blueprints[name] = self + self._got_registered_once = True + state = self.make_setup_state(app, options, first_bp_registration) + + if self.has_static_folder: + state.add_url_rule( + f"{self.static_url_path}/", + view_func=self.send_static_file, + endpoint="static", + ) + + # Merge blueprint data into parent. + if first_bp_registration or first_name_registration: + + def extend(bp_dict, parent_dict): + for key, values in bp_dict.items(): + key = name if key is None else f"{name}.{key}" + parent_dict[key].extend(values) + + for key, value in self.error_handler_spec.items(): + key = name if key is None else f"{name}.{key}" + value = defaultdict( + dict, + { + code: { + exc_class: func for exc_class, func in code_values.items() + } + for code, code_values in value.items() + }, + ) + app.error_handler_spec[key] = value + + for endpoint, func in self.view_functions.items(): + app.view_functions[endpoint] = func + + extend(self.before_request_funcs, app.before_request_funcs) + extend(self.after_request_funcs, app.after_request_funcs) + extend( + self.teardown_request_funcs, + app.teardown_request_funcs, + ) + extend(self.url_default_functions, app.url_default_functions) + extend(self.url_value_preprocessors, app.url_value_preprocessors) + extend(self.template_context_processors, app.template_context_processors) + + for deferred in self.deferred_functions: + deferred(state) + + cli_resolved_group = options.get("cli_group", self.cli_group) + + if self.cli.commands: + if cli_resolved_group is None: + app.cli.commands.update(self.cli.commands) + elif cli_resolved_group is _sentinel: + self.cli.name = name + app.cli.add_command(self.cli) + else: + self.cli.name = cli_resolved_group + app.cli.add_command(self.cli) + + for blueprint, bp_options in self._blueprints: + bp_options = bp_options.copy() + bp_url_prefix = bp_options.get("url_prefix") + + if bp_url_prefix is None: + bp_url_prefix = blueprint.url_prefix + + if state.url_prefix is not None and bp_url_prefix is not None: + bp_options["url_prefix"] = ( + state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") + ) + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: + bp_options["url_prefix"] = state.url_prefix + + bp_options["name_prefix"] = name + blueprint.register(app, bp_options) + + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[t.Callable] = None, + provide_automatic_options: t.Optional[bool] = None, + **options: t.Any, + ) -> None: + """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for + the :func:`url_for` function is prefixed with the name of the blueprint. + """ + if endpoint and "." in endpoint: + raise ValueError("'endpoint' may not contain a dot '.' character.") + + if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: + raise ValueError("'view_func' name may not contain a dot '.' character.") + + self.record( + lambda s: s.add_url_rule( + rule, + endpoint, + view_func, + provide_automatic_options=provide_automatic_options, + **options, + ) + ) + + def app_template_filter( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]: + """Register a custom template filter, available application wide. Like + :meth:`Flask.template_filter` but for a blueprint. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable: + self.add_app_template_filter(f, name=name) + return f + + return decorator + + def add_app_template_filter( + self, f: TemplateFilterCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template filter, available application wide. Like + :meth:`Flask.add_template_filter` but for a blueprint. Works exactly + like the :meth:`app_template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.filters[name or f.__name__] = f + + self.record_once(register_template) + + def app_template_test( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]: + """Register a custom template test, available application wide. Like + :meth:`Flask.template_test` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: TemplateTestCallable) -> TemplateTestCallable: + self.add_app_template_test(f, name=name) + return f + + return decorator + + def add_app_template_test( + self, f: TemplateTestCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template test, available application wide. Like + :meth:`Flask.add_template_test` but for a blueprint. Works exactly + like the :meth:`app_template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.tests[name or f.__name__] = f + + self.record_once(register_template) + + def app_template_global( + self, name: t.Optional[str] = None + ) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]: + """Register a custom template global, available application wide. Like + :meth:`Flask.template_global` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable: + self.add_app_template_global(f, name=name) + return f + + return decorator + + def add_app_template_global( + self, f: TemplateGlobalCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template global, available application wide. Like + :meth:`Flask.add_template_global` but for a blueprint. Works exactly + like the :meth:`app_template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.globals[name or f.__name__] = f + + self.record_once(register_template) + + def before_app_request(self, f: BeforeRequestCallable) -> BeforeRequestCallable: + """Like :meth:`Flask.before_request`. Such a function is executed + before each request, even if outside of a blueprint. + """ + self.record_once( + lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) + ) + return f + + def before_app_first_request( + self, f: BeforeFirstRequestCallable + ) -> BeforeFirstRequestCallable: + """Like :meth:`Flask.before_first_request`. Such a function is + executed before the first request to the application. + """ + self.record_once(lambda s: s.app.before_first_request_funcs.append(f)) + return f + + def after_app_request(self, f: AfterRequestCallable) -> AfterRequestCallable: + """Like :meth:`Flask.after_request` but for a blueprint. Such a function + is executed after each request, even if outside of the blueprint. + """ + self.record_once( + lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) + ) + return f + + def teardown_app_request(self, f: TeardownCallable) -> TeardownCallable: + """Like :meth:`Flask.teardown_request` but for a blueprint. Such a + function is executed when tearing down each request, even if outside of + the blueprint. + """ + self.record_once( + lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) + ) + return f + + def app_context_processor( + self, f: TemplateContextProcessorCallable + ) -> TemplateContextProcessorCallable: + """Like :meth:`Flask.context_processor` but for a blueprint. Such a + function is executed each request, even if outside of the blueprint. + """ + self.record_once( + lambda s: s.app.template_context_processors.setdefault(None, []).append(f) + ) + return f + + def app_errorhandler(self, code: t.Union[t.Type[Exception], int]) -> t.Callable: + """Like :meth:`Flask.errorhandler` but for a blueprint. This + handler is used for all requests, even if outside of the blueprint. + """ + + def decorator(f: "ErrorHandlerCallable") -> "ErrorHandlerCallable": + self.record_once(lambda s: s.app.errorhandler(code)(f)) + return f + + return decorator + + def app_url_value_preprocessor( + self, f: URLValuePreprocessorCallable + ) -> URLValuePreprocessorCallable: + """Same as :meth:`url_value_preprocessor` but application wide.""" + self.record_once( + lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) + ) + return f + + def app_url_defaults(self, f: URLDefaultCallable) -> URLDefaultCallable: + """Same as :meth:`url_defaults` but application wide.""" + self.record_once( + lambda s: s.app.url_default_functions.setdefault(None, []).append(f) + ) + return f diff --git a/axios-example/lib/python3.10/site-packages/flask/cli.py b/axios-example/lib/python3.10/site-packages/flask/cli.py new file mode 100644 index 0000000..36c4f1b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/cli.py @@ -0,0 +1,992 @@ +import ast +import inspect +import os +import platform +import re +import sys +import traceback +from functools import update_wrapper +from operator import attrgetter +from threading import Lock +from threading import Thread + +import click +from werkzeug.utils import import_string + +from .globals import current_app +from .helpers import get_debug_flag +from .helpers import get_env +from .helpers import get_load_dotenv + +try: + import dotenv +except ImportError: + dotenv = None + +try: + import ssl +except ImportError: + ssl = None # type: ignore + +if sys.version_info >= (3, 10): + from importlib import metadata +else: + # Use a backport on Python < 3.10. + # + # We technically have importlib.metadata on 3.8+, + # but the API changed in 3.10, so use the backport + # for consistency. + import importlib_metadata as metadata # type: ignore + + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module): + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in ("app", "application"): + app = getattr(module, attr_name, None) + + if isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + elif len(matches) > 1: + raise NoAppException( + "Detected multiple Flask applications in module" + f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'" + f" to specify the correct one." + ) + + # Search for app factory functions. + for attr_name in ("create_app", "make_app"): + app_factory = getattr(module, attr_name, None) + + if inspect.isfunction(app_factory): + try: + app = app_factory() + + if isinstance(app, Flask): + return app + except TypeError as e: + if not _called_with_wrong_args(app_factory): + raise + + raise NoAppException( + f"Detected factory {attr_name!r} in module {module.__name__!r}," + " but could not call it without arguments. Use" + f" \"FLASK_APP='{module.__name__}:{attr_name}(args)'\"" + " to specify arguments." + ) from e + + raise NoAppException( + "Failed to find Flask application or factory in module" + f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'" + " to specify one." + ) + + +def _called_with_wrong_args(f): + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the factory raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def find_app_by_string(module, app_name): + """Check if the given string is a variable name or a function. Call + a function to get the app instance, or return the variable directly. + """ + from . import Flask + + # Parse app_name as a single expression to determine if it's a valid + # attribute name or function call. + try: + expr = ast.parse(app_name.strip(), mode="eval").body + except SyntaxError: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) from None + + if isinstance(expr, ast.Name): + name = expr.id + args = [] + kwargs = {} + elif isinstance(expr, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expr.func, ast.Name): + raise NoAppException( + f"Function reference must be a simple name: {app_name!r}." + ) + + name = expr.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expr.args] + kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in expr.keywords} + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise NoAppException( + f"Failed to parse arguments as literal values: {app_name!r}." + ) from None + else: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) + + try: + attr = getattr(module, name) + except AttributeError as e: + raise NoAppException( + f"Failed to find attribute {name!r} in {module.__name__!r}." + ) from e + + # If the attribute is a function, call it with any args and kwargs + # to get the real application. + if inspect.isfunction(attr): + try: + app = attr(*args, **kwargs) + except TypeError as e: + if not _called_with_wrong_args(attr): + raise + + raise NoAppException( + f"The factory {app_name!r} in module" + f" {module.__name__!r} could not be called with the" + " specified arguments." + ) from e + else: + app = attr + + if isinstance(app, Flask): + return app + + raise NoAppException( + "A valid Flask application was not obtained from" + f" '{module.__name__}:{app_name}'." + ) + + +def prepare_import(path): + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + path = os.path.realpath(path) + + fname, ext = os.path.splitext(path) + if ext == ".py": + path = fname + + if os.path.basename(path) == "__init__": + path = os.path.dirname(path) + + module_name = [] + + # move up until outside package structure (no __init__.py) + while True: + path, name = os.path.split(path) + module_name.append(name) + + if not os.path.exists(os.path.join(path, "__init__.py")): + break + + if sys.path[0] != path: + sys.path.insert(0, path) + + return ".".join(module_name[::-1]) + + +def locate_app(module_name, app_name, raise_if_not_found=True): + __traceback_hide__ = True # noqa: F841 + + try: + __import__(module_name) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[2].tb_next: + raise NoAppException( + f"While importing {module_name!r}, an ImportError was" + f" raised:\n\n{traceback.format_exc()}" + ) from None + elif raise_if_not_found: + raise NoAppException(f"Could not import {module_name!r}.") from None + else: + return + + module = sys.modules[module_name] + + if app_name is None: + return find_best_app(module) + else: + return find_app_by_string(module, app_name) + + +def get_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + + import werkzeug + from . import __version__ + + click.echo( + f"Python {platform.python_version()}\n" + f"Flask {__version__}\n" + f"Werkzeug {werkzeug.__version__}", + color=ctx.color, + ) + ctx.exit() + + +version_option = click.Option( + ["--version"], + help="Show the flask version", + expose_value=False, + callback=get_version, + is_flag=True, + is_eager=True, +) + + +class DispatchingApp: + """Special application that dispatches to a Flask application which + is imported by name in a background thread. If an error happens + it is recorded and shown as part of the WSGI handling which in case + of the Werkzeug debugger means that it shows up in the browser. + """ + + def __init__(self, loader, use_eager_loading=None): + self.loader = loader + self._app = None + self._lock = Lock() + self._bg_loading_exc = None + + if use_eager_loading is None: + use_eager_loading = os.environ.get("WERKZEUG_RUN_MAIN") != "true" + + if use_eager_loading: + self._load_unlocked() + else: + self._load_in_background() + + def _load_in_background(self): + # Store the Click context and push it in the loader thread so + # script_info is still available. + ctx = click.get_current_context(silent=True) + + def _load_app(): + __traceback_hide__ = True # noqa: F841 + + with self._lock: + if ctx is not None: + click.globals.push_context(ctx) + + try: + self._load_unlocked() + except Exception as e: + self._bg_loading_exc = e + + t = Thread(target=_load_app, args=()) + t.start() + + def _flush_bg_loading_exception(self): + __traceback_hide__ = True # noqa: F841 + exc = self._bg_loading_exc + + if exc is not None: + self._bg_loading_exc = None + raise exc + + def _load_unlocked(self): + __traceback_hide__ = True # noqa: F841 + self._app = rv = self.loader() + self._bg_loading_exc = None + return rv + + def __call__(self, environ, start_response): + __traceback_hide__ = True # noqa: F841 + if self._app is not None: + return self._app(environ, start_response) + self._flush_bg_loading_exception() + with self._lock: + if self._app is not None: + rv = self._app + else: + rv = self._load_unlocked() + return rv(environ, start_response) + + +class ScriptInfo: + """Helper object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + """ + + def __init__(self, app_import_path=None, create_app=None, set_debug_flag=True): + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path or os.environ.get("FLASK_APP") + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data = {} + self.set_debug_flag = set_debug_flag + self._loaded_app = None + + def load_app(self): + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + __traceback_hide__ = True # noqa: F841 + + if self._loaded_app is not None: + return self._loaded_app + + if self.create_app is not None: + app = self.create_app() + else: + if self.app_import_path: + path, name = ( + re.split(r":(?![\\/])", self.app_import_path, 1) + [None] + )[:2] + import_name = prepare_import(path) + app = locate_app(import_name, name) + else: + for path in ("wsgi.py", "app.py"): + import_name = prepare_import(path) + app = locate_app(import_name, None, raise_if_not_found=False) + + if app: + break + + if not app: + raise NoAppException( + "Could not locate a Flask application. You did not provide " + 'the "FLASK_APP" environment variable, and a "wsgi.py" or ' + '"app.py" module was not found in the current directory.' + ) + + if self.set_debug_flag: + # Update the app's debug flag through the descriptor so that + # other values repopulate as well. + app.debug = get_debug_flag() + + self._loaded_app = app + return app + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + + +def with_appcontext(f): + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. If callbacks are registered directly + to the ``app.cli`` object then they are wrapped with this function + by default unless it's disabled. + """ + + @click.pass_context + def decorator(__ctx, *args, **kwargs): + with __ctx.ensure_object(ScriptInfo).load_app().app_context(): + return __ctx.invoke(f, *args, **kwargs) + + return update_wrapper(decorator, f) + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop("with_appcontext", True) + + def decorator(f): + if wrap_for_ctx: + f = with_appcontext(f) + return click.Group.command(self, *args, **kwargs)(f) + + return decorator + + def group(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault("cls", AppGroup) + return click.Group.group(self, *args, **kwargs) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands will be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info and + returns the loaded app. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param set_debug_flag: Set the app's debug flag based on the active + environment + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment variables + from :file:`.env` and :file:`.flaskenv` files. + """ + + def __init__( + self, + add_default_commands=True, + create_app=None, + add_version_option=True, + load_dotenv=True, + set_debug_flag=True, + **extra, + ): + params = list(extra.pop("params", None) or ()) + + if add_version_option: + params.append(version_option) + + AppGroup.__init__(self, params=params, **extra) + self.create_app = create_app + self.load_dotenv = load_dotenv + self.set_debug_flag = set_debug_flag + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + self.add_command(routes_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self): + if self._loaded_plugin_commands: + return + + for ep in metadata.entry_points(group="flask.commands"): + self.add_command(ep.load(), ep.name) + + self._loaded_plugin_commands = True + + def get_command(self, ctx, name): + self._load_plugin_commands() + # Look up built-in and plugin commands, which should be + # available even if the app fails to load. + rv = super().get_command(ctx, name) + + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + + # Look up commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + return info.load_app().cli.get_command(ctx, name) + except NoAppException as e: + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + + def list_commands(self, ctx): + self._load_plugin_commands() + # Start with the built-in and plugin commands. + rv = set(super().list_commands(ctx)) + info = ctx.ensure_object(ScriptInfo) + + # Add commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except NoAppException as e: + # When an app couldn't be loaded, show the error message + # without the traceback. + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + except Exception: + # When any other errors occurred during loading, show the + # full traceback. + click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") + + return sorted(rv) + + def main(self, *args, **kwargs): + # Set a global flag that indicates that we were invoked from the + # command line interface. This is detected by Flask.run to make the + # call into a no-op. This is necessary to avoid ugly errors when the + # script that is loaded here also attempts to start a server. + os.environ["FLASK_RUN_FROM_CLI"] = "true" + + if get_load_dotenv(self.load_dotenv): + load_dotenv() + + obj = kwargs.get("obj") + + if obj is None: + obj = ScriptInfo( + create_app=self.create_app, set_debug_flag=self.set_debug_flag + ) + + kwargs["obj"] = obj + kwargs.setdefault("auto_envvar_prefix", "FLASK") + return super().main(*args, **kwargs) + + +def _path_is_ancestor(path, other): + """Take ``other`` and remove the length of ``path`` from it. Then join it + to ``path``. If it is the original value, ``path`` is an ancestor of + ``other``.""" + return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other + + +def load_dotenv(path=None): + """Load "dotenv" files in order of precedence to set environment variables. + + If an env var is already set it is not overwritten, so earlier files in the + list are preferred over later files. + + This is a no-op if `python-dotenv`_ is not installed. + + .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme + + :param path: Load the file at this location instead of searching. + :return: ``True`` if a file was loaded. + + .. versionchanged:: 1.1.0 + Returns ``False`` when python-dotenv is not installed, or when + the given path isn't a file. + + .. versionchanged:: 2.0 + When loading the env files, set the default encoding to UTF-8. + + .. versionadded:: 1.0 + """ + if dotenv is None: + if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): + click.secho( + " * Tip: There are .env or .flaskenv files present." + ' Do "pip install python-dotenv" to use them.', + fg="yellow", + err=True, + ) + + return False + + # if the given path specifies the actual file then return True, + # else False + if path is not None: + if os.path.isfile(path): + return dotenv.load_dotenv(path, encoding="utf-8") + + return False + + new_dir = None + + for name in (".env", ".flaskenv"): + path = dotenv.find_dotenv(name, usecwd=True) + + if not path: + continue + + if new_dir is None: + new_dir = os.path.dirname(path) + + dotenv.load_dotenv(path, encoding="utf-8") + + return new_dir is not None # at least one file was located and loaded + + +def show_server_banner(env, debug, app_import_path, eager_loading): + """Show extra startup messages the first time the server is run, + ignoring the reloader. + """ + if os.environ.get("WERKZEUG_RUN_MAIN") == "true": + return + + if app_import_path is not None: + message = f" * Serving Flask app {app_import_path!r}" + + if not eager_loading: + message += " (lazy loading)" + + click.echo(message) + + click.echo(f" * Environment: {env}") + + if env == "production": + click.secho( + " WARNING: This is a development server. Do not use it in" + " a production deployment.", + fg="red", + ) + click.secho(" Use a production WSGI server instead.", dim=True) + + if debug is not None: + click.echo(f" * Debug mode: {'on' if debug else 'off'}") + + +class CertParamType(click.ParamType): + """Click option type for the ``--cert`` option. Allows either an + existing file, the string ``'adhoc'``, or an import for a + :class:`~ssl.SSLContext` object. + """ + + name = "path" + + def __init__(self): + self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) + + def convert(self, value, param, ctx): + if ssl is None: + raise click.BadParameter( + 'Using "--cert" requires Python to be compiled with SSL support.', + ctx, + param, + ) + + try: + return self.path_type(value, param, ctx) + except click.BadParameter: + value = click.STRING(value, param, ctx).lower() + + if value == "adhoc": + try: + import cryptography # noqa: F401 + except ImportError: + raise click.BadParameter( + "Using ad-hoc certificates requires the cryptography library.", + ctx, + param, + ) from None + + return value + + obj = import_string(value, silent=True) + + if isinstance(obj, ssl.SSLContext): + return obj + + raise + + +def _validate_key(ctx, param, value): + """The ``--key`` option must be specified when ``--cert`` is a file. + Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. + """ + cert = ctx.params.get("cert") + is_adhoc = cert == "adhoc" + is_context = ssl and isinstance(cert, ssl.SSLContext) + + if value is not None: + if is_adhoc: + raise click.BadParameter( + 'When "--cert" is "adhoc", "--key" is not used.', ctx, param + ) + + if is_context: + raise click.BadParameter( + 'When "--cert" is an SSLContext object, "--key is not used.', ctx, param + ) + + if not cert: + raise click.BadParameter('"--cert" must also be specified.', ctx, param) + + ctx.params["cert"] = cert, value + + else: + if cert and not (is_adhoc or is_context): + raise click.BadParameter('Required when using "--cert".', ctx, param) + + return value + + +class SeparatedPathType(click.Path): + """Click option type that accepts a list of values separated by the + OS's path separator (``:``, ``;`` on Windows). Each value is + validated as a :class:`click.Path` type. + """ + + def convert(self, value, param, ctx): + items = self.split_envvar_value(value) + super_convert = super().convert + return [super_convert(item, param, ctx) for item in items] + + +@click.command("run", short_help="Run a development server.") +@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") +@click.option("--port", "-p", default=5000, help="The port to bind to.") +@click.option( + "--cert", + type=CertParamType(), + help="Specify a certificate file to use HTTPS.", + is_eager=True, +) +@click.option( + "--key", + type=click.Path(exists=True, dir_okay=False, resolve_path=True), + callback=_validate_key, + expose_value=False, + help="The key file to use when specifying a certificate.", +) +@click.option( + "--reload/--no-reload", + default=None, + help="Enable or disable the reloader. By default the reloader " + "is active if debug is enabled.", +) +@click.option( + "--debugger/--no-debugger", + default=None, + help="Enable or disable the debugger. By default the debugger " + "is active if debug is enabled.", +) +@click.option( + "--eager-loading/--lazy-loading", + default=None, + help="Enable or disable eager loading. By default eager " + "loading is enabled if the reloader is disabled.", +) +@click.option( + "--with-threads/--without-threads", + default=True, + help="Enable or disable multithreading.", +) +@click.option( + "--extra-files", + default=None, + type=SeparatedPathType(), + help=( + "Extra files that trigger a reload on change. Multiple paths" + f" are separated by {os.path.pathsep!r}." + ), +) +@click.option( + "--exclude-patterns", + default=None, + type=SeparatedPathType(), + help=( + "Files matching these fnmatch patterns will not trigger a reload" + " on change. Multiple patterns are separated by" + f" {os.path.pathsep!r}." + ), +) +@pass_script_info +def run_command( + info, + host, + port, + reload, + debugger, + eager_loading, + with_threads, + cert, + extra_files, + exclude_patterns, +): + """Run a local development server. + + This server is for development purposes only. It does not provide + the stability, security, or performance of production WSGI servers. + + The reloader and debugger are enabled by default if + FLASK_ENV=development or FLASK_DEBUG=1. + """ + debug = get_debug_flag() + + if reload is None: + reload = debug + + if debugger is None: + debugger = debug + + show_server_banner(get_env(), debug, info.app_import_path, eager_loading) + app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) + + from werkzeug.serving import run_simple + + run_simple( + host, + port, + app, + use_reloader=reload, + use_debugger=debugger, + threaded=with_threads, + ssl_context=cert, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + ) + + +@click.command("shell", short_help="Run a shell in the app context.") +@with_appcontext +def shell_command() -> None: + """Run an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to its configuration. + + This is useful for executing small snippets of management code + without having to manually configure the application. + """ + import code + from .globals import _app_ctx_stack + + app = _app_ctx_stack.top.app + banner = ( + f"Python {sys.version} on {sys.platform}\n" + f"App: {app.import_name} [{app.env}]\n" + f"Instance: {app.instance_path}" + ) + ctx: dict = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup) as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(app.make_shell_context()) + + # Site, customize, or startup script can set a hook to call when + # entering interactive mode. The default one sets up readline with + # tab and history completion. + interactive_hook = getattr(sys, "__interactivehook__", None) + + if interactive_hook is not None: + try: + import readline + from rlcompleter import Completer + except ImportError: + pass + else: + # rlcompleter uses __main__.__dict__ by default, which is + # flask.__main__. Use the shell context instead. + readline.set_completer(Completer(ctx).complete) + + interactive_hook() + + code.interact(banner=banner, local=ctx) + + +@click.command("routes", short_help="Show the routes for the app.") +@click.option( + "--sort", + "-s", + type=click.Choice(("endpoint", "methods", "rule", "match")), + default="endpoint", + help=( + 'Method to sort routes by. "match" is the order that Flask will match ' + "routes when dispatching a request." + ), +) +@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") +@with_appcontext +def routes_command(sort: str, all_methods: bool) -> None: + """Show all registered routes with endpoints and methods.""" + + rules = list(current_app.url_map.iter_rules()) + if not rules: + click.echo("No routes were registered.") + return + + ignored_methods = set(() if all_methods else ("HEAD", "OPTIONS")) + + if sort in ("endpoint", "rule"): + rules = sorted(rules, key=attrgetter(sort)) + elif sort == "methods": + rules = sorted(rules, key=lambda rule: sorted(rule.methods)) # type: ignore + + rule_methods = [ + ", ".join(sorted(rule.methods - ignored_methods)) # type: ignore + for rule in rules + ] + + headers = ("Endpoint", "Methods", "Rule") + widths = ( + max(len(rule.endpoint) for rule in rules), + max(len(methods) for methods in rule_methods), + max(len(rule.rule) for rule in rules), + ) + widths = [max(len(h), w) for h, w in zip(headers, widths)] + row = "{{0:<{0}}} {{1:<{1}}} {{2:<{2}}}".format(*widths) + + click.echo(row.format(*headers).strip()) + click.echo(row.format(*("-" * width for width in widths))) + + for rule, methods in zip(rules, rule_methods): + click.echo(row.format(rule.endpoint, methods, rule.rule).rstrip()) + + +cli = FlaskGroup( + help="""\ +A general utility script for Flask applications. + +Provides commands from Flask, extensions, and the application. Loads the +application defined in the FLASK_APP environment variable, or from a wsgi.py +file. Setting the FLASK_ENV environment variable to 'development' will enable +debug mode. + +\b + {prefix}{cmd} FLASK_APP=hello.py + {prefix}{cmd} FLASK_ENV=development + {prefix}flask run +""".format( + cmd="export" if os.name == "posix" else "set", + prefix="$ " if os.name == "posix" else "> ", + ) +) + + +def main() -> None: + cli.main() + + +if __name__ == "__main__": + main() diff --git a/axios-example/lib/python3.10/site-packages/flask/config.py b/axios-example/lib/python3.10/site-packages/flask/config.py new file mode 100644 index 0000000..7b6a137 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/config.py @@ -0,0 +1,337 @@ +import errno +import json +import os +import types +import typing as t + +from werkzeug.utils import import_string + + +class ConfigAttribute: + """Makes an attribute forward to the config""" + + def __init__(self, name: str, get_converter: t.Optional[t.Callable] = None) -> None: + self.__name__ = name + self.get_converter = get_converter + + def __get__(self, obj: t.Any, owner: t.Any = None) -> t.Any: + if obj is None: + return self + rv = obj.config[self.__name__] + if self.get_converter is not None: + rv = self.get_converter(rv) + return rv + + def __set__(self, obj: t.Any, value: t.Any) -> None: + obj.config[self.__name__] = value + + +class Config(dict): + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__(self, root_path: str, defaults: t.Optional[dict] = None) -> None: + super().__init__(defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name: str, silent: bool = False) -> bool: + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError( + f"The environment variable {variable_name!r} is not set" + " and as such configuration could not be loaded. Set" + " this variable and make it point to a configuration" + " file" + ) + return self.from_pyfile(rv, silent=silent) + + def from_prefixed_env( + self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads + ) -> bool: + """Load any environment variables that start with ``FLASK_``, + dropping the prefix from the env key for the config key. Values + are passed through a loading function to attempt to convert them + to more specific types than strings. + + Keys are loaded in :func:`sorted` order. + + The default loading function attempts to parse values as any + valid JSON type, including dicts and lists. + + Specific items in nested dicts can be set by separating the + keys with double underscores (``__``). If an intermediate key + doesn't exist, it will be initialized to an empty dict. + + :param prefix: Load env vars that start with this prefix, + separated with an underscore (``_``). + :param loads: Pass each string value to this function and use + the returned value as the config value. If any error is + raised it is ignored and the value remains a string. The + default is :func:`json.loads`. + + .. versionadded:: 2.1 + """ + prefix = f"{prefix}_" + len_prefix = len(prefix) + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + # Change to key.removeprefix(prefix) on Python >= 3.9. + key = key[len_prefix:] + + if "__" not in key: + # A non-nested key, set directly. + self[key] = value + continue + + # Traverse nested dictionaries with keys separated by "__". + current = self + *parts, tail = key.split("__") + + for part in parts: + # If an intermediate dict does not exist, create it. + if part not in current: + current[part] = {} + + current = current[part] + + current[tail] = value + + return True + + def from_pyfile(self, filename: str, silent: bool = False) -> bool: + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType("config") + d.__file__ = filename + try: + with open(filename, mode="rb") as config_file: + exec(compile(config_file.read(), filename, "exec"), d.__dict__) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): + return False + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + self.from_object(d) + return True + + def from_object(self, obj: t.Union[object, str]) -> None: + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + Nothing is done to the object before loading. If the object is a + class and has ``@property`` attributes, it needs to be + instantiated before being passed to this method. + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, str): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_file( + self, + filename: str, + load: t.Callable[[t.IO[t.Any]], t.Mapping], + silent: bool = False, + ) -> bool: + """Update the values in the config from a file that is loaded + using the ``load`` parameter. The loaded data is passed to the + :meth:`from_mapping` method. + + .. code-block:: python + + import json + app.config.from_file("config.json", load=json.load) + + import toml + app.config.from_file("config.toml", load=toml.load) + + :param filename: The path to the data file. This can be an + absolute path or relative to the config root path. + :param load: A callable that takes a file handle and returns a + mapping of loaded data from the file. + :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` + implements a ``read`` method. + :param silent: Ignore the file if it doesn't exist. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 2.0 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename) as f: + obj = load(f) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + + return self.from_mapping(obj) + + def from_mapping( + self, mapping: t.Optional[t.Mapping[str, t.Any]] = None, **kwargs: t.Any + ) -> bool: + """Updates the config like :meth:`update` ignoring items with non-upper + keys. + :return: Always returns ``True``. + + .. versionadded:: 0.11 + """ + mappings: t.Dict[str, t.Any] = {} + if mapping is not None: + mappings.update(mapping) + mappings.update(kwargs) + for key, value in mappings.items(): + if key.isupper(): + self[key] = value + return True + + def get_namespace( + self, namespace: str, lowercase: bool = True, trim_namespace: bool = True + ) -> t.Dict[str, t.Any]: + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in self.items(): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace) :] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self) -> str: + return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/axios-example/lib/python3.10/site-packages/flask/ctx.py b/axios-example/lib/python3.10/site-packages/flask/ctx.py new file mode 100644 index 0000000..3ed8fd3 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/ctx.py @@ -0,0 +1,513 @@ +import sys +import typing as t +from functools import update_wrapper +from types import TracebackType + +from werkzeug.exceptions import HTTPException + +from .globals import _app_ctx_stack +from .globals import _request_ctx_stack +from .signals import appcontext_popped +from .signals import appcontext_pushed +from .typing import AfterRequestCallable + +if t.TYPE_CHECKING: + from .app import Flask + from .sessions import SessionMixin + from .wrappers import Request + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals: + """A plain object. Used as a namespace for storing data during an + application context. + + Creating an app context automatically creates this object, which is + made available as the :data:`g` proxy. + + .. describe:: 'key' in g + + Check whether an attribute is present. + + .. versionadded:: 0.10 + + .. describe:: iter(g) + + Return an iterator over the attribute names. + + .. versionadded:: 0.10 + """ + + # Define attr methods to let mypy know this is a namespace object + # that has arbitrary attributes. + + def __getattr__(self, name: str) -> t.Any: + try: + return self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + self.__dict__[name] = value + + def __delattr__(self, name: str) -> None: + try: + del self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def get(self, name: str, default: t.Optional[t.Any] = None) -> t.Any: + """Get an attribute by name, or a default value. Like + :meth:`dict.get`. + + :param name: Name of attribute to get. + :param default: Value to return if the attribute is not present. + + .. versionadded:: 0.10 + """ + return self.__dict__.get(name, default) + + def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: + """Get and remove an attribute by name. Like :meth:`dict.pop`. + + :param name: Name of attribute to pop. + :param default: Value to return if the attribute is not present, + instead of raising a ``KeyError``. + + .. versionadded:: 0.11 + """ + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name: str, default: t.Any = None) -> t.Any: + """Get the value of an attribute if it is present, otherwise + set and return a default value. Like :meth:`dict.setdefault`. + + :param name: Name of attribute to get. + :param default: Value to set and return if the attribute is not + present. + + .. versionadded:: 0.11 + """ + return self.__dict__.setdefault(name, default) + + def __contains__(self, item: str) -> bool: + return item in self.__dict__ + + def __iter__(self) -> t.Iterator[str]: + return iter(self.__dict__) + + def __repr__(self) -> str: + top = _app_ctx_stack.top + if top is not None: + return f"" + return object.__repr__(self) + + +def after_this_request(f: AfterRequestCallable) -> AfterRequestCallable: + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + top = _request_ctx_stack.top + + if top is None: + raise RuntimeError( + "This decorator can only be used when a request context is" + " active, such as within a view function." + ) + + top._after_request_functions.append(f) + return f + + +def copy_current_request_context(f: t.Callable) -> t.Callable: + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. The current session is also + included in the copied request context. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request or + # flask.session like you would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + top = _request_ctx_stack.top + + if top is None: + raise RuntimeError( + "This decorator can only be used when a request context is" + " active, such as within a view function." + ) + + reqctx = top.copy() + + def wrapper(*args, **kwargs): + with reqctx: + return reqctx.app.ensure_sync(f)(*args, **kwargs) + + return update_wrapper(wrapper, f) + + +def has_request_context() -> bool: + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g`) for truthness:: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _request_ctx_stack.top is not None + + +def has_app_context() -> bool: + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _app_ctx_stack.top is not None + + +class AppContext: + """The application context binds an application object implicitly + to the current thread or greenlet, similar to how the + :class:`RequestContext` binds request information. The application + context is also implicitly created if a request context is created + but the application is not on top of the individual application + context. + """ + + def __init__(self, app: "Flask") -> None: + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g = app.app_ctx_globals_class() + + # Like request context, app contexts can be pushed multiple times + # but there a basic "refcount" is enough to track them. + self._refcnt = 0 + + def push(self) -> None: + """Binds the app context to the current context.""" + self._refcnt += 1 + _app_ctx_stack.push(self) + appcontext_pushed.send(self.app) + + def pop(self, exc: t.Optional[BaseException] = _sentinel) -> None: # type: ignore + """Pops the app context.""" + try: + self._refcnt -= 1 + if self._refcnt <= 0: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + rv = _app_ctx_stack.pop() + assert rv is self, f"Popped wrong app context. ({rv!r} instead of {self!r})" + appcontext_popped.send(self.app) + + def __enter__(self) -> "AppContext": + self.push() + return self + + def __exit__( + self, + exc_type: t.Optional[type], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.pop(exc_value) + + +class RequestContext: + """The request context contains all request relevant information. It is + created at the beginning of the request and pushed to the + `_request_ctx_stack` and removed at the end of it. It will create the + URL adapter and request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the request + for you. In debug mode the request context is kept around if + exceptions happen so that interactive debuggers have a chance to + introspect the data. With 0.4 this can also be forced for requests + that did not fail and outside of ``DEBUG`` mode. By setting + ``'flask._preserve_context'`` to ``True`` on the WSGI environment the + context will not pop itself at the end of the request. This is used by + the :meth:`~flask.Flask.test_client` for example to implement the + deferred cleanup functionality. + + You might find this helpful for unittests where you need the + information from the context local around for a little longer. Make + sure to properly :meth:`~werkzeug.LocalStack.pop` the stack yourself in + that situation, otherwise your unittests will leak memory. + """ + + def __init__( + self, + app: "Flask", + environ: dict, + request: t.Optional["Request"] = None, + session: t.Optional["SessionMixin"] = None, + ) -> None: + self.app = app + if request is None: + request = app.request_class(environ) + self.request = request + self.url_adapter = None + try: + self.url_adapter = app.create_url_adapter(self.request) + except HTTPException as e: + self.request.routing_exception = e + self.flashes = None + self.session = session + + # Request contexts can be pushed multiple times and interleaved with + # other request contexts. Now only if the last level is popped we + # get rid of them. Additionally if an application context is missing + # one is created implicitly so for each level we add this information + self._implicit_app_ctx_stack: t.List[t.Optional["AppContext"]] = [] + + # indicator if the context was preserved. Next time another context + # is pushed the preserved context is popped. + self.preserved = False + + # remembers the exception for pop if there is one in case the context + # preservation kicks in. + self._preserved_exc = None + + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions: t.List[AfterRequestCallable] = [] + + @property + def g(self) -> _AppCtxGlobals: + import warnings + + warnings.warn( + "Accessing 'g' on the request context is deprecated and" + " will be removed in Flask 2.2. Access `g` directly or from" + "the application context instead.", + DeprecationWarning, + stacklevel=2, + ) + return _app_ctx_stack.top.g + + @g.setter + def g(self, value: _AppCtxGlobals) -> None: + import warnings + + warnings.warn( + "Setting 'g' on the request context is deprecated and" + " will be removed in Flask 2.2. Set it on the application" + " context instead.", + DeprecationWarning, + stacklevel=2, + ) + _app_ctx_stack.top.g = value + + def copy(self) -> "RequestContext": + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + + .. versionchanged:: 1.1 + The current session object is used instead of reloading the original + data. This prevents `flask.session` pointing to an out-of-date object. + """ + return self.__class__( + self.app, + environ=self.request.environ, + request=self.request, + session=self.session, + ) + + def match_request(self) -> None: + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + result = self.url_adapter.match(return_rule=True) # type: ignore + self.request.url_rule, self.request.view_args = result # type: ignore + except HTTPException as e: + self.request.routing_exception = e + + def push(self) -> None: + """Binds the request context to the current context.""" + # If an exception occurs in debug mode or if context preservation is + # activated under exception situations exactly one context stays + # on the stack. The rationale is that you want to access that + # information under debug situations. However if someone forgets to + # pop that context again we want to make sure that on the next push + # it's invalidated, otherwise we run at risk that something leaks + # memory. This is usually only a problem in test suite since this + # functionality is not active in production environments. + top = _request_ctx_stack.top + if top is not None and top.preserved: + top.pop(top._preserved_exc) + + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _app_ctx_stack.top + if app_ctx is None or app_ctx.app != self.app: + app_ctx = self.app.app_context() + app_ctx.push() + self._implicit_app_ctx_stack.append(app_ctx) + else: + self._implicit_app_ctx_stack.append(None) + + _request_ctx_stack.push(self) + + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + # Only open a new session if this is the first time the request was + # pushed, otherwise stream_with_context loses the session. + if self.session is None: + session_interface = self.app.session_interface + self.session = session_interface.open_session(self.app, self.request) + + if self.session is None: + self.session = session_interface.make_null_session(self.app) + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() + + def pop(self, exc: t.Optional[BaseException] = _sentinel) -> None: # type: ignore + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + app_ctx = self._implicit_app_ctx_stack.pop() + clear_request = False + + try: + if not self._implicit_app_ctx_stack: + self.preserved = False + self._preserved_exc = None + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + request_close = getattr(self.request, "close", None) + if request_close is not None: + request_close() + clear_request = True + finally: + rv = _request_ctx_stack.pop() + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + rv.request.environ["werkzeug.request"] = None + + # Get rid of the app as well if necessary. + if app_ctx is not None: + app_ctx.pop(exc) + + assert ( + rv is self + ), f"Popped wrong request context. ({rv!r} instead of {self!r})" + + def auto_pop(self, exc: t.Optional[BaseException]) -> None: + if self.request.environ.get("flask._preserve_context") or ( + exc is not None and self.app.preserve_context_on_exception + ): + self.preserved = True + self._preserved_exc = exc # type: ignore + else: + self.pop(exc) + + def __enter__(self) -> "RequestContext": + self.push() + return self + + def __exit__( + self, + exc_type: t.Optional[type], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + # do not pop the request stack if we are in debug mode and an + # exception happened. This will allow the debugger to still + # access the request object in the interactive shell. Furthermore + # the context can be force kept alive for the test client. + # See flask.testing for how this works. + self.auto_pop(exc_value) + + def __repr__(self) -> str: + return ( + f"<{type(self).__name__} {self.request.url!r}" + f" [{self.request.method}] of {self.app.name}>" + ) diff --git a/axios-example/lib/python3.10/site-packages/flask/debughelpers.py b/axios-example/lib/python3.10/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..27d378c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/debughelpers.py @@ -0,0 +1,174 @@ +import os +import typing as t +from warnings import warn + +from .app import Flask +from .blueprints import Blueprint +from .globals import _request_ctx_stack + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request, key): + form_matches = request.form.getlist(key) + buf = [ + f"You tried to access the file {key!r} in the request.files" + " dictionary but it does not exist. The mimetype for the" + f" request is {request.mimetype!r} instead of" + " 'multipart/form-data' which means that no file contents" + " were transmitted. To fix this error you should provide" + ' enctype="multipart/form-data" in your form.' + ] + if form_matches: + names = ", ".join(repr(x) for x in form_matches) + buf.append( + "\n\nThe browser instead transmitted some file names. " + f"This was submitted: {names}" + ) + self.msg = "".join(buf) + + def __str__(self): + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised in debug mode if a routing redirect + would cause the browser to drop the method or body. This happens + when method is not GET, HEAD or OPTIONS and the status code is not + 307 or 308. + """ + + def __init__(self, request): + exc = request.routing_exception + buf = [ + f"A request was sent to '{request.url}', but routing issued" + f" a redirect to the canonical URL '{exc.new_url}'." + ] + + if f"{request.base_url}/" == exc.new_url.partition("?")[0]: + buf.append( + " The URL was defined with a trailing slash. Flask" + " will redirect to the URL with a trailing slash if it" + " was accessed without one." + ) + + buf.append( + " Send requests to the canonical URL, or use 307 or 308 for" + " routing redirects. Otherwise, browsers will drop form" + " data.\n\n" + "This exception is only raised in debug mode." + ) + super().__init__("".join(buf)) + + +def attach_enctype_error_multidict(request): + """Patch ``request.files.__getitem__`` to raise a descriptive error + about ``enctype=multipart/form-data``. + + :param request: The request to patch. + :meta private: + """ + oldcls = request.files.__class__ + + class newcls(oldcls): + def __getitem__(self, key): + try: + return super().__getitem__(key) + except KeyError as e: + if key not in request.form: + raise + + raise DebugFilesKeyError(request, key).with_traceback( + e.__traceback__ + ) from None + + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader) -> t.Generator: + yield f"class: {type(loader).__module__}.{type(loader).__name__}" + for key, value in sorted(loader.__dict__.items()): + if key.startswith("_"): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, str) for x in value): + continue + yield f"{key}:" + for item in value: + yield f" - {item}" + continue + elif not isinstance(value, (str, int, float, bool)): + continue + yield f"{key}: {value!r}" + + +def explain_template_loading_attempts(app: Flask, template, attempts) -> None: + """This should help developers understand what failed""" + info = [f"Locating template {template!r}:"] + total_found = 0 + blueprint = None + reqctx = _request_ctx_stack.top + if reqctx is not None and reqctx.request.blueprint is not None: + blueprint = reqctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, Flask): + src_info = f"application {srcobj.import_name!r}" + elif isinstance(srcobj, Blueprint): + src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" + else: + src_info = repr(srcobj) + + info.append(f"{idx + 1:5}: trying loader of {src_info}") + + for line in _dump_loader_info(loader): + info.append(f" {line}") + + if triple is None: + detail = "no match" + else: + detail = f"found ({triple[1] or ''!r})" + total_found += 1 + info.append(f" -> {detail}") + + seems_fishy = False + if total_found == 0: + info.append("Error: the template could not be found.") + seems_fishy = True + elif total_found > 1: + info.append("Warning: multiple loaders returned a match for the template.") + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append( + " The template was looked up from an endpoint that belongs" + f" to the blueprint {blueprint!r}." + ) + info.append(" Maybe you did not place a template in the right folder?") + info.append(" See https://flask.palletsprojects.com/blueprints/#templates") + + app.logger.info("\n".join(info)) + + +def explain_ignored_app_run() -> None: + if os.environ.get("WERKZEUG_RUN_MAIN") != "true": + warn( + Warning( + "Silently ignoring app.run() because the application is" + " run from the flask command line executable. Consider" + ' putting app.run() behind an if __name__ == "__main__"' + " guard to silence this warning." + ), + stacklevel=3, + ) diff --git a/axios-example/lib/python3.10/site-packages/flask/globals.py b/axios-example/lib/python3.10/site-packages/flask/globals.py new file mode 100644 index 0000000..6d91c75 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/globals.py @@ -0,0 +1,59 @@ +import typing as t +from functools import partial + +from werkzeug.local import LocalProxy +from werkzeug.local import LocalStack + +if t.TYPE_CHECKING: + from .app import Flask + from .ctx import _AppCtxGlobals + from .sessions import SessionMixin + from .wrappers import Request + +_request_ctx_err_msg = """\ +Working outside of request context. + +This typically means that you attempted to use functionality that needed +an active HTTP request. Consult the documentation on testing for +information about how to avoid this problem.\ +""" +_app_ctx_err_msg = """\ +Working outside of application context. + +This typically means that you attempted to use functionality that needed +to interface with the current application object in some way. To solve +this, set up an application context with app.app_context(). See the +documentation for more information.\ +""" + + +def _lookup_req_object(name): + top = _request_ctx_stack.top + if top is None: + raise RuntimeError(_request_ctx_err_msg) + return getattr(top, name) + + +def _lookup_app_object(name): + top = _app_ctx_stack.top + if top is None: + raise RuntimeError(_app_ctx_err_msg) + return getattr(top, name) + + +def _find_app(): + top = _app_ctx_stack.top + if top is None: + raise RuntimeError(_app_ctx_err_msg) + return top.app + + +# context locals +_request_ctx_stack = LocalStack() +_app_ctx_stack = LocalStack() +current_app: "Flask" = LocalProxy(_find_app) # type: ignore +request: "Request" = LocalProxy(partial(_lookup_req_object, "request")) # type: ignore +session: "SessionMixin" = LocalProxy( # type: ignore + partial(_lookup_req_object, "session") +) +g: "_AppCtxGlobals" = LocalProxy(partial(_lookup_app_object, "g")) # type: ignore diff --git a/axios-example/lib/python3.10/site-packages/flask/helpers.py b/axios-example/lib/python3.10/site-packages/flask/helpers.py new file mode 100644 index 0000000..fe47500 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/helpers.py @@ -0,0 +1,790 @@ +import os +import pkgutil +import socket +import sys +import typing as t +import warnings +from datetime import datetime +from functools import lru_cache +from functools import update_wrapper +from threading import RLock + +import werkzeug.utils +from werkzeug.routing import BuildError +from werkzeug.urls import url_quote + +from .globals import _app_ctx_stack +from .globals import _request_ctx_stack +from .globals import current_app +from .globals import request +from .globals import session +from .signals import message_flashed + +if t.TYPE_CHECKING: + from .wrappers import Response + + +def get_env() -> str: + """Get the environment the app is running in, indicated by the + :envvar:`FLASK_ENV` environment variable. The default is + ``'production'``. + """ + return os.environ.get("FLASK_ENV") or "production" + + +def get_debug_flag() -> bool: + """Get whether debug mode should be enabled for the app, indicated + by the :envvar:`FLASK_DEBUG` environment variable. The default is + ``True`` if :func:`.get_env` returns ``'development'``, or ``False`` + otherwise. + """ + val = os.environ.get("FLASK_DEBUG") + + if not val: + return get_env() == "development" + + return val.lower() not in ("0", "false", "no") + + +def get_load_dotenv(default: bool = True) -> bool: + """Get whether the user has disabled loading dotenv files by setting + :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load the + files. + + :param default: What to return if the env var isn't set. + """ + val = os.environ.get("FLASK_SKIP_DOTENV") + + if not val: + return default + + return val.lower() in ("0", "false", "no") + + +def stream_with_context( + generator_or_function: t.Union[ + t.Iterator[t.AnyStr], t.Callable[..., t.Iterator[t.AnyStr]] + ] +) -> t.Iterator[t.AnyStr]: + """Request contexts disappear when the response is started on the server. + This is done for efficiency reasons and to make it less likely to encounter + memory leaks with badly written WSGI middlewares. The downside is that if + you are using streamed responses, the generator cannot access request bound + information any more. + + This function however can help you keep the context around for longer:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + @stream_with_context + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(generate()) + + Alternatively it can also be used around a specific generator:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) # type: ignore + except TypeError: + + def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: + gen = generator_or_function(*args, **kwargs) # type: ignore + return stream_with_context(gen) + + return update_wrapper(decorator, generator_or_function) # type: ignore + + def generator() -> t.Generator: + ctx = _request_ctx_stack.top + if ctx is None: + raise RuntimeError( + "Attempted to stream with context but " + "there was no context in the first place to keep around." + ) + with ctx: + # Dummy sentinel. Has to be inside the context block or we're + # not actually keeping the context around. + yield None + + # The try/finally is here so that if someone passes a WSGI level + # iterator in we're still running the cleanup logic. Generators + # don't need that because they are closed on their destruction + # automatically. + try: + yield from gen + finally: + if hasattr(gen, "close"): + gen.close() # type: ignore + + # The trick is to start the generator. Then the code execution runs until + # the first dummy None is yielded at which point the context was already + # pushed. This item is discarded. Then when the iteration continues the + # real generator is executed. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g + + +def make_response(*args: t.Any) -> "Response": + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) # type: ignore + + +def url_for(endpoint: str, **values: t.Any) -> str: + """Generates a URL to the given endpoint with the method provided. + + Variable arguments that are unknown to the target endpoint are appended + to the generated URL as query arguments. If the value of a query argument + is ``None``, the whole pair is skipped. In case blueprints are active + you can shortcut references to the same blueprint by prefixing the + local endpoint with a dot (``.``). + + This will reference the index function local to the current blueprint:: + + url_for('.index') + + See :ref:`url-building`. + + Configuration values ``APPLICATION_ROOT`` and ``SERVER_NAME`` are only used when + generating URLs outside of a request context. + + To integrate applications, :class:`Flask` has a hook to intercept URL build + errors through :attr:`Flask.url_build_error_handlers`. The `url_for` + function results in a :exc:`~werkzeug.routing.BuildError` when the current + app does not have a URL for the given endpoint and values. When it does, the + :data:`~flask.current_app` calls its :attr:`~Flask.url_build_error_handlers` if + it is not ``None``, which can return a string to use as the result of + `url_for` (instead of `url_for`'s default to raise the + :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception. + An example:: + + def external_url_handler(error, endpoint, values): + "Looks up an external URL when `url_for` cannot build a URL." + # This is an example of hooking the build_error_handler. + # Here, lookup_url is some utility function you've built + # which looks up the endpoint in some external URL registry. + url = lookup_url(endpoint, **values) + if url is None: + # External lookup did not have a URL. + # Re-raise the BuildError, in context of original traceback. + exc_type, exc_value, tb = sys.exc_info() + if exc_value is error: + raise exc_type(exc_value).with_traceback(tb) + else: + raise error + # url_for will use this result, instead of raising BuildError. + return url + + app.url_build_error_handlers.append(external_url_handler) + + Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and + `endpoint` and `values` are the arguments passed into `url_for`. Note + that this is for building URLs outside the current application, and not for + handling 404 NotFound errors. + + .. versionadded:: 0.10 + The `_scheme` parameter was added. + + .. versionadded:: 0.9 + The `_anchor` and `_method` parameters were added. + + .. versionadded:: 0.9 + Calls :meth:`Flask.handle_build_error` on + :exc:`~werkzeug.routing.BuildError`. + + :param endpoint: the endpoint of the URL (name of the function) + :param values: the variable arguments of the URL rule + :param _external: if set to ``True``, an absolute URL is generated. Server + address can be changed via ``SERVER_NAME`` configuration variable which + falls back to the `Host` header, then to the IP and port of the request. + :param _scheme: a string specifying the desired URL scheme. The `_external` + parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default + behavior uses the same scheme as the current request, or + :data:`PREFERRED_URL_SCHEME` if no request context is available. + This also can be set to an empty string to build protocol-relative + URLs. + :param _anchor: if provided this is added as anchor to the URL. + :param _method: if provided this explicitly specifies an HTTP method. + """ + appctx = _app_ctx_stack.top + reqctx = _request_ctx_stack.top + + if appctx is None: + raise RuntimeError( + "Attempted to generate a URL without the application context being" + " pushed. This has to be executed when application context is" + " available." + ) + + # If request specific information is available we have some extra + # features that support "relative" URLs. + if reqctx is not None: + url_adapter = reqctx.url_adapter + blueprint_name = request.blueprint + + if endpoint[:1] == ".": + if blueprint_name is not None: + endpoint = f"{blueprint_name}{endpoint}" + else: + endpoint = endpoint[1:] + + external = values.pop("_external", False) + + # Otherwise go with the url adapter from the appctx and make + # the URLs external by default. + else: + url_adapter = appctx.url_adapter + + if url_adapter is None: + raise RuntimeError( + "Application was not able to create a URL adapter for request" + " independent URL generation. You might be able to fix this by" + " setting the SERVER_NAME config variable." + ) + + external = values.pop("_external", True) + + anchor = values.pop("_anchor", None) + method = values.pop("_method", None) + scheme = values.pop("_scheme", None) + appctx.app.inject_url_defaults(endpoint, values) + + # This is not the best way to deal with this but currently the + # underlying Werkzeug router does not support overriding the scheme on + # a per build call basis. + old_scheme = None + if scheme is not None: + if not external: + raise ValueError("When specifying _scheme, _external must be True") + old_scheme = url_adapter.url_scheme + url_adapter.url_scheme = scheme + + try: + try: + rv = url_adapter.build( + endpoint, values, method=method, force_external=external + ) + finally: + if old_scheme is not None: + url_adapter.url_scheme = old_scheme + except BuildError as error: + # We need to inject the values again so that the app callback can + # deal with that sort of stuff. + values["_external"] = external + values["_anchor"] = anchor + values["_method"] = method + values["_scheme"] = scheme + return appctx.app.handle_url_build_error(error, endpoint, values) + + if anchor is not None: + rv += f"#{url_quote(anchor)}" + return rv + + +def get_template_attribute(template_name: str, attribute: str) -> t.Any: + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, attribute) + + +def flash(message: str, category: str = "message") -> None: + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get("_flashes", []) + flashes.append((category, message)) + session["_flashes"] = flashes + message_flashed.send( + current_app._get_current_object(), # type: ignore + message=message, + category=category, + ) + + +def get_flashed_messages( + with_categories: bool = False, category_filter: t.Iterable[str] = () +) -> t.Union[t.List[str], t.List[t.Tuple[str, str]]]: + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :doc:`/patterns/flashing` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: filter of categories to limit return values. Only + categories in the list will be returned. + """ + flashes = _request_ctx_stack.top.flashes + if flashes is None: + _request_ctx_stack.top.flashes = flashes = ( + session.pop("_flashes") if "_flashes" in session else [] + ) + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def _prepare_send_file_kwargs( + download_name: t.Optional[str] = None, + attachment_filename: t.Optional[str] = None, + etag: t.Optional[t.Union[bool, str]] = None, + add_etags: t.Optional[t.Union[bool]] = None, + max_age: t.Optional[ + t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]] + ] = None, + cache_timeout: t.Optional[int] = None, + **kwargs: t.Any, +) -> t.Dict[str, t.Any]: + if attachment_filename is not None: + warnings.warn( + "The 'attachment_filename' parameter has been renamed to" + " 'download_name'. The old name will be removed in Flask" + " 2.2.", + DeprecationWarning, + stacklevel=3, + ) + download_name = attachment_filename + + if cache_timeout is not None: + warnings.warn( + "The 'cache_timeout' parameter has been renamed to" + " 'max_age'. The old name will be removed in Flask 2.2.", + DeprecationWarning, + stacklevel=3, + ) + max_age = cache_timeout + + if add_etags is not None: + warnings.warn( + "The 'add_etags' parameter has been renamed to 'etag'. The" + " old name will be removed in Flask 2.2.", + DeprecationWarning, + stacklevel=3, + ) + etag = add_etags + + if max_age is None: + max_age = current_app.get_send_file_max_age + + kwargs.update( + environ=request.environ, + download_name=download_name, + etag=etag, + max_age=max_age, + use_x_sendfile=current_app.use_x_sendfile, + response_class=current_app.response_class, + _root_path=current_app.root_path, # type: ignore + ) + return kwargs + + +def send_file( + path_or_file: t.Union[os.PathLike, str, t.BinaryIO], + mimetype: t.Optional[str] = None, + as_attachment: bool = False, + download_name: t.Optional[str] = None, + attachment_filename: t.Optional[str] = None, + conditional: bool = True, + etag: t.Union[bool, str] = True, + add_etags: t.Optional[bool] = None, + last_modified: t.Optional[t.Union[datetime, int, float]] = None, + max_age: t.Optional[ + t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]] + ] = None, + cache_timeout: t.Optional[int] = None, +): + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve + user-requested paths from within a directory. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, configuring Flask with + ``USE_X_SENDFILE = True`` will tell the server to send the given + path, which is much more efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + + .. versionchanged:: 2.0 + ``download_name`` replaces the ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces the ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces the ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + Passing a file-like object that inherits from + :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather + than sending an empty file. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionchanged:: 1.1 + ``filename`` may be a :class:`~os.PathLike` object. + + .. versionchanged:: 1.1 + Passing a :class:`~io.BytesIO` object supports range requests. + + .. versionchanged:: 1.0.3 + Filenames are encoded with ASCII instead of Latin-1 for broader + compatibility with WSGI servers. + + .. versionchanged:: 1.0 + UTF-8 filenames as specified in :rfc:`2231` are supported. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file + objects. If you want to use automatic MIME and etag support, + pass a filename via ``filename_or_fp`` or + ``attachment_filename``. + + .. versionchanged:: 0.12 + ``attachment_filename`` is preferred over ``filename`` for MIME + detection. + + .. versionchanged:: 0.9 + ``cache_timeout`` defaults to + :meth:`Flask.get_send_file_max_age`. + + .. versionchanged:: 0.7 + MIME guessing and etag support for file-like objects was + deprecated because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. + + .. versionchanged:: 0.5 + The ``add_etags``, ``cache_timeout`` and ``conditional`` + parameters were added. The default behavior is to add etags. + + .. versionadded:: 0.2 + """ + return werkzeug.utils.send_file( + **_prepare_send_file_kwargs( + path_or_file=path_or_file, + environ=request.environ, + mimetype=mimetype, + as_attachment=as_attachment, + download_name=download_name, + attachment_filename=attachment_filename, + conditional=conditional, + etag=etag, + add_etags=add_etags, + last_modified=last_modified, + max_age=max_age, + cache_timeout=cache_timeout, + ) + ) + + +def send_from_directory( + directory: t.Union[os.PathLike, str], + path: t.Union[os.PathLike, str], + filename: t.Optional[str] = None, + **kwargs: t.Any, +) -> "Response": + """Send a file from within a directory using :func:`send_file`. + + .. code-block:: python + + @app.route("/uploads/") + def download_file(name): + return send_from_directory( + app.config['UPLOAD_FOLDER'], name, as_attachment=True + ) + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under. + :param path: The path to the file to send, relative to + ``directory``. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionchanged:: 2.0 + ``path`` replaces the ``filename`` parameter. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionadded:: 0.5 + """ + if filename is not None: + warnings.warn( + "The 'filename' parameter has been renamed to 'path'. The" + " old name will be removed in Flask 2.2.", + DeprecationWarning, + stacklevel=2, + ) + path = filename + + return werkzeug.utils.send_from_directory( # type: ignore + directory, path, **_prepare_send_file_kwargs(**kwargs) + ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + loader = pkgutil.get_loader(import_name) + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None or import_name == "__main__": + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) # type: ignore + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) + + +class locked_cached_property(werkzeug.utils.cached_property): + """A :func:`property` that is only evaluated once. Like + :class:`werkzeug.utils.cached_property` except access uses a lock + for thread safety. + + .. versionchanged:: 2.0 + Inherits from Werkzeug's ``cached_property`` (and ``property``). + """ + + def __init__( + self, + fget: t.Callable[[t.Any], t.Any], + name: t.Optional[str] = None, + doc: t.Optional[str] = None, + ) -> None: + super().__init__(fget, name=name, doc=doc) + self.lock = RLock() + + def __get__(self, obj: object, type: type = None) -> t.Any: # type: ignore + if obj is None: + return self + + with self.lock: + return super().__get__(obj, type=type) + + def __set__(self, obj: object, value: t.Any) -> None: + with self.lock: + super().__set__(obj, value) + + def __delete__(self, obj: object) -> None: + with self.lock: + super().__delete__(obj) + + +def is_ip(value: str) -> bool: + """Determine if the given string is an IP address. + + :param value: value to check + :type value: str + + :return: True if string is an IP address + :rtype: bool + """ + for family in (socket.AF_INET, socket.AF_INET6): + try: + socket.inet_pton(family, value) + except OSError: + pass + else: + return True + + return False + + +@lru_cache(maxsize=None) +def _split_blueprint_path(name: str) -> t.List[str]: + out: t.List[str] = [name] + + if "." in name: + out.extend(_split_blueprint_path(name.rpartition(".")[0])) + + return out diff --git a/axios-example/lib/python3.10/site-packages/flask/json/__init__.py b/axios-example/lib/python3.10/site-packages/flask/json/__init__.py new file mode 100644 index 0000000..edc9793 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/flask/json/__init__.py @@ -0,0 +1,303 @@ +import dataclasses +import decimal +import json as _json +import typing as t +import uuid +from datetime import date + +from jinja2.utils import htmlsafe_json_dumps as _jinja_htmlsafe_dumps +from werkzeug.http import http_date + +from ..globals import current_app +from ..globals import request + +if t.TYPE_CHECKING: + from ..app import Flask + from ..wrappers import Response + + +class JSONEncoder(_json.JSONEncoder): + """The default JSON encoder. Handles extra types compared to the + built-in :class:`json.JSONEncoder`. + + - :class:`datetime.datetime` and :class:`datetime.date` are + serialized to :rfc:`822` strings. This is the same as the HTTP + date format. + - :class:`uuid.UUID` is serialized to a string. + - :class:`dataclasses.dataclass` is passed to + :func:`dataclasses.asdict`. + - :class:`~markupsafe.Markup` (or any object with a ``__html__`` + method) will call the ``__html__`` method to get a string. + + Assign a subclass of this to :attr:`flask.Flask.json_encoder` or + :attr:`flask.Blueprint.json_encoder` to override the default. + """ + + def default(self, o: t.Any) -> t.Any: + """Convert ``o`` to a JSON serializable type. See + :meth:`json.JSONEncoder.default`. Python does not support + overriding how basic types like ``str`` or ``list`` are + serialized, they are handled before this method. + """ + if isinstance(o, date): + return http_date(o) + if isinstance(o, (decimal.Decimal, uuid.UUID)): + return str(o) + if dataclasses and dataclasses.is_dataclass(o): + return dataclasses.asdict(o) + if hasattr(o, "__html__"): + return str(o.__html__()) + return super().default(o) + + +class JSONDecoder(_json.JSONDecoder): + """The default JSON decoder. + + This does not change any behavior from the built-in + :class:`json.JSONDecoder`. + + Assign a subclass of this to :attr:`flask.Flask.json_decoder` or + :attr:`flask.Blueprint.json_decoder` to override the default. + """ + + +def _dump_arg_defaults( + kwargs: t.Dict[str, t.Any], app: t.Optional["Flask"] = None +) -> None: + """Inject default arguments for dump functions.""" + if app is None: + app = current_app + + if app: + cls = app.json_encoder + bp = app.blueprints.get(request.blueprint) if request else None # type: ignore + if bp is not None and bp.json_encoder is not None: + cls = bp.json_encoder + + # Only set a custom encoder if it has custom behavior. This is + # faster on PyPy. + if cls is not _json.JSONEncoder: + kwargs.setdefault("cls", cls) + + kwargs.setdefault("cls", cls) + kwargs.setdefault("ensure_ascii", app.config["JSON_AS_ASCII"]) + kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"]) + else: + kwargs.setdefault("sort_keys", True) + kwargs.setdefault("cls", JSONEncoder) + + +def _load_arg_defaults( + kwargs: t.Dict[str, t.Any], app: t.Optional["Flask"] = None +) -> None: + """Inject default arguments for load functions.""" + if app is None: + app = current_app + + if app: + cls = app.json_decoder + bp = app.blueprints.get(request.blueprint) if request else None # type: ignore + if bp is not None and bp.json_decoder is not None: + cls = bp.json_decoder + + # Only set a custom decoder if it has custom behavior. This is + # faster on PyPy. + if cls not in {JSONDecoder, _json.JSONDecoder}: + kwargs.setdefault("cls", cls) + + +def dumps(obj: t.Any, app: t.Optional["Flask"] = None, **kwargs: t.Any) -> str: + """Serialize an object to a string of JSON. + + Takes the same arguments as the built-in :func:`json.dumps`, with + some defaults from application configuration. + + :param obj: Object to serialize to JSON. + :param app: Use this app's config instead of the active app context + or defaults. + :param kwargs: Extra arguments passed to :func:`json.dumps`. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 2.0 + ``encoding`` is deprecated and will be removed in Flask 2.1. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + _dump_arg_defaults(kwargs, app=app) + return _json.dumps(obj, **kwargs) + + +def dump( + obj: t.Any, fp: t.IO[str], app: t.Optional["Flask"] = None, **kwargs: t.Any +) -> None: + """Serialize an object to JSON written to a file object. + + Takes the same arguments as the built-in :func:`json.dump`, with + some defaults from application configuration. + + :param obj: Object to serialize to JSON. + :param fp: File object to write JSON to. + :param app: Use this app's config instead of the active app context + or defaults. + :param kwargs: Extra arguments passed to :func:`json.dump`. + + .. versionchanged:: 2.0 + Writing to a binary file, and the ``encoding`` argument, is + deprecated and will be removed in Flask 2.1. + """ + _dump_arg_defaults(kwargs, app=app) + _json.dump(obj, fp, **kwargs) + + +def loads( + s: t.Union[str, bytes], + app: t.Optional["Flask"] = None, + **kwargs: t.Any, +) -> t.Any: + """Deserialize an object from a string of JSON. + + Takes the same arguments as the built-in :func:`json.loads`, with + some defaults from application configuration. + + :param s: JSON string to deserialize. + :param app: Use this app's config instead of the active app context + or defaults. + :param kwargs: Extra arguments passed to :func:`json.loads`. + + .. versionchanged:: 2.0 + ``encoding`` is deprecated and will be removed in Flask 2.1. The + data must be a string or UTF-8 bytes. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + _load_arg_defaults(kwargs, app=app) + return _json.loads(s, **kwargs) + + +def load(fp: t.IO[str], app: t.Optional["Flask"] = None, **kwargs: t.Any) -> t.Any: + """Deserialize an object from JSON read from a file object. + + Takes the same arguments as the built-in :func:`json.load`, with + some defaults from application configuration. + + :param fp: File object to read JSON from. + :param app: Use this app's config instead of the active app context + or defaults. + :param kwargs: Extra arguments passed to :func:`json.load`. + + .. versionchanged:: 2.0 + ``encoding`` is deprecated and will be removed in Flask 2.1. The + file must be text mode, or binary mode with UTF-8 bytes. + """ + _load_arg_defaults(kwargs, app=app) + return _json.load(fp, **kwargs) + + +def htmlsafe_dumps(obj: t.Any, **kwargs: t.Any) -> str: + """Serialize an object to a string of JSON with :func:`dumps`, then + replace HTML-unsafe characters with Unicode escapes and mark the + result safe with :class:`~markupsafe.Markup`. + + This is available in templates as the ``|tojson`` filter. + + The returned string is safe to render in HTML documents and + `` + + + +

+""" + +FOOTER = """\ + +
+ +
+
+

Console Locked

+

+ The console is locked and needs to be unlocked by entering the PIN. + You can find the PIN printed out on the standard output of your + shell that runs the server. +

+

PIN: + + +

+
+
+ + +""" + +PAGE_HTML = ( + HEADER + + """\ +

%(exception_type)s

+
+

%(exception)s

+
+

Traceback (most recent call last)

+%(summary)s +
+

+ This is the Copy/Paste friendly version of the traceback. +

+ +
+
+ The debugger caught an exception in your WSGI application. You can now + look at the traceback which led to the error. + If you enable JavaScript you can also use additional features such as code + execution (if the evalex feature is enabled), automatic pasting of the + exceptions and much more. +
+""" + + FOOTER + + """ + +""" +) + +CONSOLE_HTML = ( + HEADER + + """\ +

Interactive Console

+
+In this console you can execute Python expressions in the context of the +application. The initial namespace was created by the debugger automatically. +
+
The Console requires JavaScript.
+""" + + FOOTER +) + +SUMMARY_HTML = """\ +
+ %(title)s +
    %(frames)s
+ %(description)s +
+""" + +FRAME_HTML = """\ +
+

File "%(filename)s", + line %(lineno)s, + in %(function_name)s

+
%(lines)s
+
+""" + + +def _process_traceback( + exc: BaseException, + te: t.Optional[traceback.TracebackException] = None, + *, + skip: int = 0, + hide: bool = True, +) -> traceback.TracebackException: + if te is None: + te = traceback.TracebackException.from_exception(exc, lookup_lines=False) + + # Get the frames the same way StackSummary.extract did, in order + # to match each frame with the FrameSummary to augment. + frame_gen = traceback.walk_tb(exc.__traceback__) + limit = getattr(sys, "tracebacklimit", None) + + if limit is not None: + if limit < 0: + limit = 0 + + frame_gen = itertools.islice(frame_gen, limit) + + if skip: + frame_gen = itertools.islice(frame_gen, skip, None) + del te.stack[:skip] + + new_stack: t.List[DebugFrameSummary] = [] + hidden = False + + # Match each frame with the FrameSummary that was generated. + # Hide frames using Paste's __traceback_hide__ rules. Replace + # all visible FrameSummary with DebugFrameSummary. + for (f, _), fs in zip(frame_gen, te.stack): + if hide: + hide_value = f.f_locals.get("__traceback_hide__", False) + + if hide_value in {"before", "before_and_this"}: + new_stack = [] + hidden = False + + if hide_value == "before_and_this": + continue + elif hide_value in {"reset", "reset_and_this"}: + hidden = False + + if hide_value == "reset_and_this": + continue + elif hide_value in {"after", "after_and_this"}: + hidden = True + + if hide_value == "after_and_this": + continue + elif hide_value or hidden: + continue + + new_stack.append( + DebugFrameSummary( + filename=fs.filename, + lineno=fs.lineno, + name=fs.name, + locals=f.f_locals, + globals=f.f_globals, + ) + ) + + # The codeop module is used to compile code from the interactive + # debugger. Hide any codeop frames from the bottom of the traceback. + while new_stack: + module = new_stack[0].global_ns.get("__name__") + + if module is None: + module = new_stack[0].local_ns.get("__name__") + + if module == "codeop": + del new_stack[0] + else: + break + + te.stack[:] = new_stack + + if te.__context__: + context_exc = t.cast(BaseException, exc.__context__) + te.__context__ = _process_traceback(context_exc, te.__context__, hide=hide) + + if te.__cause__: + cause_exc = t.cast(BaseException, exc.__cause__) + te.__cause__ = _process_traceback(cause_exc, te.__cause__, hide=hide) + + return te + + +class DebugTraceback: + __slots__ = ("_te", "_cache_all_tracebacks", "_cache_all_frames") + + def __init__( + self, + exc: BaseException, + te: t.Optional[traceback.TracebackException] = None, + *, + skip: int = 0, + hide: bool = True, + ) -> None: + self._te = _process_traceback(exc, te, skip=skip, hide=hide) + + def __str__(self) -> str: + return f"<{type(self).__name__} {self._te}>" + + @cached_property + def all_tracebacks( + self, + ) -> t.List[t.Tuple[t.Optional[str], traceback.TracebackException]]: + out = [] + current = self._te + + while current is not None: + if current.__cause__ is not None: + chained_msg = ( + "The above exception was the direct cause of the" + " following exception" + ) + chained_exc = current.__cause__ + elif current.__context__ is not None and not current.__suppress_context__: + chained_msg = ( + "During handling of the above exception, another" + " exception occurred" + ) + chained_exc = current.__context__ + else: + chained_msg = None + chained_exc = None + + out.append((chained_msg, current)) + current = chained_exc + + return out + + @cached_property + def all_frames(self) -> t.List["DebugFrameSummary"]: + return [ + f for _, te in self.all_tracebacks for f in te.stack # type: ignore[misc] + ] + + def render_traceback_text(self) -> str: + return "".join(self._te.format()) + + def render_traceback_html(self, include_title: bool = True) -> str: + library_frames = [f.is_library for f in self.all_frames] + mark_library = 0 < sum(library_frames) < len(library_frames) + rows = [] + + if not library_frames: + classes = "traceback noframe-traceback" + else: + classes = "traceback" + + for msg, current in reversed(self.all_tracebacks): + row_parts = [] + + if msg is not None: + row_parts.append(f'
  • {msg}:
    ') + + for frame in current.stack: + frame = t.cast(DebugFrameSummary, frame) + info = f' title="{escape(frame.info)}"' if frame.info else "" + row_parts.append(f"{frame.render_html(mark_library)}") + + rows.append("\n".join(row_parts)) + + is_syntax_error = issubclass(self._te.exc_type, SyntaxError) + + if include_title: + if is_syntax_error: + title = "Syntax Error" + else: + title = "Traceback (most recent call last):" + else: + title = "" + + exc_full = escape("".join(self._te.format_exception_only())) + + if is_syntax_error: + description = f"
    {exc_full}
    " + else: + description = f"
    {exc_full}
    " + + return SUMMARY_HTML % { + "classes": classes, + "title": f"

    {title}

    ", + "frames": "\n".join(rows), + "description": description, + } + + def render_debugger_html( + self, evalex: bool, secret: str, evalex_trusted: bool + ) -> str: + exc_lines = list(self._te.format_exception_only()) + plaintext = "".join(self._te.format()) + return PAGE_HTML % { + "evalex": "true" if evalex else "false", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "false", + "title": exc_lines[0], + "exception": escape("".join(exc_lines)), + "exception_type": escape(self._te.exc_type.__name__), + "summary": self.render_traceback_html(include_title=False), + "plaintext": escape(plaintext), + "plaintext_cs": re.sub("-{2,}", "-", plaintext), + "secret": secret, + } + + +class DebugFrameSummary(traceback.FrameSummary): + """A :class:`traceback.FrameSummary` that can evaluate code in the + frame's namespace. + """ + + __slots__ = ( + "local_ns", + "global_ns", + "_cache_info", + "_cache_is_library", + "_cache_console", + ) + + def __init__( + self, + *, + locals: t.Dict[str, t.Any], + globals: t.Dict[str, t.Any], + **kwargs: t.Any, + ) -> None: + super().__init__(locals=None, **kwargs) + self.local_ns = locals + self.global_ns = globals + + @cached_property + def info(self) -> t.Optional[str]: + return self.local_ns.get("__traceback_info__") + + @cached_property + def is_library(self) -> bool: + return any( + self.filename.startswith(os.path.realpath(path)) + for path in sysconfig.get_paths().values() + ) + + @cached_property + def console(self) -> Console: + return Console(self.global_ns, self.local_ns) + + def eval(self, code: str) -> t.Any: + return self.console.eval(code) + + def render_html(self, mark_library: bool) -> str: + context = 5 + lines = linecache.getlines(self.filename) + line_idx = self.lineno - 1 # type: ignore[operator] + start_idx = max(0, line_idx - context) + stop_idx = min(len(lines), line_idx + context + 1) + rendered_lines = [] + + def render_line(line: str, cls: str) -> None: + line = line.expandtabs().rstrip() + stripped_line = line.strip() + prefix = len(line) - len(stripped_line) + rendered_lines.append( + f'
    {" " * prefix}'
    +                f"{escape(stripped_line) if stripped_line else ' '}
    " + ) + + if lines: + for line in lines[start_idx:line_idx]: + render_line(line, "before") + + render_line(lines[line_idx], "current") + + for line in lines[line_idx + 1 : stop_idx]: + render_line(line, "after") + + return FRAME_HTML % { + "id": id(self), + "filename": escape(self.filename), + "lineno": self.lineno, + "function_name": escape(self.name), + "lines": "\n".join(rendered_lines), + "library": "library" if mark_library and self.is_library else "", + } + + +def render_console_html(secret: str, evalex_trusted: bool) -> str: + return CONSOLE_HTML % { + "evalex": "true", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "true", + "title": "Console", + "secret": secret, + } diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/exceptions.py b/axios-example/lib/python3.10/site-packages/werkzeug/exceptions.py new file mode 100644 index 0000000..d089942 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/exceptions.py @@ -0,0 +1,882 @@ +"""Implements a number of Python exceptions which can be raised from within +a view to trigger a standard HTTP non-200 response. + +Usage Example +------------- + +.. code-block:: python + + from werkzeug.wrappers.request import Request + from werkzeug.exceptions import HTTPException, NotFound + + def view(request): + raise NotFound() + + @Request.application + def application(request): + try: + return view(request) + except HTTPException as e: + return e + +As you can see from this example those exceptions are callable WSGI +applications. However, they are not Werkzeug response objects. You +can get a response object by calling ``get_response()`` on a HTTP +exception. + +Keep in mind that you may have to pass an environ (WSGI) or scope +(ASGI) to ``get_response()`` because some errors fetch additional +information relating to the request. + +If you want to hook in a different exception page to say, a 404 status +code, you can add a second except for a specific subclass of an error: + +.. code-block:: python + + @Request.application + def application(request): + try: + return view(request) + except NotFound as e: + return not_found(request) + except HTTPException as e: + return e + +""" +import typing as t +from datetime import datetime +from html import escape + +from ._internal import _get_environ + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + from .datastructures import WWWAuthenticate + from .sansio.response import Response + from .wrappers.request import Request as WSGIRequest # noqa: F401 + from .wrappers.response import Response as WSGIResponse # noqa: F401 + + +class HTTPException(Exception): + """The base class for all HTTP exceptions. This exception can be called as a WSGI + application to render a default error page or you can catch the subclasses + of it independently and render nicer error messages. + + .. versionchanged:: 2.1 + Removed the ``wrap`` class method. + """ + + code: t.Optional[int] = None + description: t.Optional[str] = None + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + super().__init__() + if description is not None: + self.description = description + self.response = response + + @property + def name(self) -> str: + """The status name.""" + from .http import HTTP_STATUS_CODES + + return HTTP_STATUS_CODES.get(self.code, "Unknown Error") # type: ignore + + def get_description( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> str: + """Get the description.""" + if self.description is None: + description = "" + elif not isinstance(self.description, str): + description = str(self.description) + else: + description = self.description + + description = escape(description).replace("\n", "
    ") + return f"

    {description}

    " + + def get_body( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> str: + """Get the HTML body.""" + return ( + "\n" + "\n" + f"{self.code} {escape(self.name)}\n" + f"

    {escape(self.name)}

    \n" + f"{self.get_description(environ)}\n" + ) + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + """Get a list of headers.""" + return [("Content-Type", "text/html; charset=utf-8")] + + def get_response( + self, + environ: t.Optional[t.Union["WSGIEnvironment", "WSGIRequest"]] = None, + scope: t.Optional[dict] = None, + ) -> "Response": + """Get a response object. If one was passed to the exception + it's returned directly. + + :param environ: the optional environ for the request. This + can be used to modify the response depending + on how the request looked like. + :return: a :class:`Response` object or a subclass thereof. + """ + from .wrappers.response import Response as WSGIResponse # noqa: F811 + + if self.response is not None: + return self.response + if environ is not None: + environ = _get_environ(environ) + headers = self.get_headers(environ, scope) + return WSGIResponse(self.get_body(environ, scope), self.code, headers) + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Call the exception as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + """ + response = t.cast("WSGIResponse", self.get_response(environ)) + return response(environ, start_response) + + def __str__(self) -> str: + code = self.code if self.code is not None else "???" + return f"{code} {self.name}: {self.description}" + + def __repr__(self) -> str: + code = self.code if self.code is not None else "???" + return f"<{type(self).__name__} '{code}: {self.name}'>" + + +class BadRequest(HTTPException): + """*400* `Bad Request` + + Raise if the browser sends something to the application the application + or server cannot handle. + """ + + code = 400 + description = ( + "The browser (or proxy) sent a request that this server could " + "not understand." + ) + + +class BadRequestKeyError(BadRequest, KeyError): + """An exception that is used to signal both a :exc:`KeyError` and a + :exc:`BadRequest`. Used by many of the datastructures. + """ + + _description = BadRequest.description + #: Show the KeyError along with the HTTP error message in the + #: response. This should be disabled in production, but can be + #: useful in a debug mode. + show_exception = False + + def __init__(self, arg: t.Optional[str] = None, *args: t.Any, **kwargs: t.Any): + super().__init__(*args, **kwargs) + + if arg is None: + KeyError.__init__(self) + else: + KeyError.__init__(self, arg) + + @property # type: ignore + def description(self) -> str: # type: ignore + if self.show_exception: + return ( + f"{self._description}\n" + f"{KeyError.__name__}: {KeyError.__str__(self)}" + ) + + return self._description + + @description.setter + def description(self, value: str) -> None: + self._description = value + + +class ClientDisconnected(BadRequest): + """Internal exception that is raised if Werkzeug detects a disconnected + client. Since the client is already gone at that point attempting to + send the error message to the client might not work and might ultimately + result in another exception in the server. Mainly this is here so that + it is silenced by default as far as Werkzeug is concerned. + + Since disconnections cannot be reliably detected and are unspecified + by WSGI to a large extent this might or might not be raised if a client + is gone. + + .. versionadded:: 0.8 + """ + + +class SecurityError(BadRequest): + """Raised if something triggers a security error. This is otherwise + exactly like a bad request error. + + .. versionadded:: 0.9 + """ + + +class BadHost(BadRequest): + """Raised if the submitted host is badly formatted. + + .. versionadded:: 0.11.2 + """ + + +class Unauthorized(HTTPException): + """*401* ``Unauthorized`` + + Raise if the user is not authorized to access a resource. + + The ``www_authenticate`` argument should be used to set the + ``WWW-Authenticate`` header. This is used for HTTP basic auth and + other schemes. Use :class:`~werkzeug.datastructures.WWWAuthenticate` + to create correctly formatted values. Strictly speaking a 401 + response is invalid if it doesn't provide at least one value for + this header, although real clients typically don't care. + + :param description: Override the default message used for the body + of the response. + :param www-authenticate: A single value, or list of values, for the + WWW-Authenticate header(s). + + .. versionchanged:: 2.0 + Serialize multiple ``www_authenticate`` items into multiple + ``WWW-Authenticate`` headers, rather than joining them + into a single value, for better interoperability. + + .. versionchanged:: 0.15.3 + If the ``www_authenticate`` argument is not set, the + ``WWW-Authenticate`` header is not set. + + .. versionchanged:: 0.15.3 + The ``response`` argument was restored. + + .. versionchanged:: 0.15.1 + ``description`` was moved back as the first argument, restoring + its previous position. + + .. versionchanged:: 0.15.0 + ``www_authenticate`` was added as the first argument, ahead of + ``description``. + """ + + code = 401 + description = ( + "The server could not verify that you are authorized to access" + " the URL requested. You either supplied the wrong credentials" + " (e.g. a bad password), or your browser doesn't understand" + " how to supply the credentials required." + ) + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + www_authenticate: t.Optional[ + t.Union["WWWAuthenticate", t.Iterable["WWWAuthenticate"]] + ] = None, + ) -> None: + super().__init__(description, response) + + from .datastructures import WWWAuthenticate + + if isinstance(www_authenticate, WWWAuthenticate): + www_authenticate = (www_authenticate,) + + self.www_authenticate = www_authenticate + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.www_authenticate: + headers.extend(("WWW-Authenticate", str(x)) for x in self.www_authenticate) + return headers + + +class Forbidden(HTTPException): + """*403* `Forbidden` + + Raise if the user doesn't have the permission for the requested resource + but was authenticated. + """ + + code = 403 + description = ( + "You don't have the permission to access the requested" + " resource. It is either read-protected or not readable by the" + " server." + ) + + +class NotFound(HTTPException): + """*404* `Not Found` + + Raise if a resource does not exist and never existed. + """ + + code = 404 + description = ( + "The requested URL was not found on the server. If you entered" + " the URL manually please check your spelling and try again." + ) + + +class MethodNotAllowed(HTTPException): + """*405* `Method Not Allowed` + + Raise if the server used a method the resource does not handle. For + example `POST` if the resource is view only. Especially useful for REST. + + The first argument for this exception should be a list of allowed methods. + Strictly speaking the response would be invalid if you don't provide valid + methods in the header which you can do with that list. + """ + + code = 405 + description = "The method is not allowed for the requested URL." + + def __init__( + self, + valid_methods: t.Optional[t.Iterable[str]] = None, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + """Takes an optional list of valid http methods + starting with werkzeug 0.3 the list will be mandatory.""" + super().__init__(description=description, response=response) + self.valid_methods = valid_methods + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.valid_methods: + headers.append(("Allow", ", ".join(self.valid_methods))) + return headers + + +class NotAcceptable(HTTPException): + """*406* `Not Acceptable` + + Raise if the server can't return any content conforming to the + `Accept` headers of the client. + """ + + code = 406 + description = ( + "The resource identified by the request is only capable of" + " generating response entities which have content" + " characteristics not acceptable according to the accept" + " headers sent in the request." + ) + + +class RequestTimeout(HTTPException): + """*408* `Request Timeout` + + Raise to signalize a timeout. + """ + + code = 408 + description = ( + "The server closed the network connection because the browser" + " didn't finish the request within the specified time." + ) + + +class Conflict(HTTPException): + """*409* `Conflict` + + Raise to signal that a request cannot be completed because it conflicts + with the current state on the server. + + .. versionadded:: 0.7 + """ + + code = 409 + description = ( + "A conflict happened while processing the request. The" + " resource might have been modified while the request was being" + " processed." + ) + + +class Gone(HTTPException): + """*410* `Gone` + + Raise if a resource existed previously and went away without new location. + """ + + code = 410 + description = ( + "The requested URL is no longer available on this server and" + " there is no forwarding address. If you followed a link from a" + " foreign page, please contact the author of this page." + ) + + +class LengthRequired(HTTPException): + """*411* `Length Required` + + Raise if the browser submitted data but no ``Content-Length`` header which + is required for the kind of processing the server does. + """ + + code = 411 + description = ( + "A request with this method requires a valid Content-" + "Length header." + ) + + +class PreconditionFailed(HTTPException): + """*412* `Precondition Failed` + + Status code used in combination with ``If-Match``, ``If-None-Match``, or + ``If-Unmodified-Since``. + """ + + code = 412 + description = ( + "The precondition on the request for the URL failed positive evaluation." + ) + + +class RequestEntityTooLarge(HTTPException): + """*413* `Request Entity Too Large` + + The status code one should return if the data submitted exceeded a given + limit. + """ + + code = 413 + description = "The data value transmitted exceeds the capacity limit." + + +class RequestURITooLarge(HTTPException): + """*414* `Request URI Too Large` + + Like *413* but for too long URLs. + """ + + code = 414 + description = ( + "The length of the requested URL exceeds the capacity limit for" + " this server. The request cannot be processed." + ) + + +class UnsupportedMediaType(HTTPException): + """*415* `Unsupported Media Type` + + The status code returned if the server is unable to handle the media type + the client transmitted. + """ + + code = 415 + description = ( + "The server does not support the media type transmitted in the request." + ) + + +class RequestedRangeNotSatisfiable(HTTPException): + """*416* `Requested Range Not Satisfiable` + + The client asked for an invalid part of the file. + + .. versionadded:: 0.7 + """ + + code = 416 + description = "The server cannot provide the requested range." + + def __init__( + self, + length: t.Optional[int] = None, + units: str = "bytes", + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + """Takes an optional `Content-Range` header value based on ``length`` + parameter. + """ + super().__init__(description=description, response=response) + self.length = length + self.units = units + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.length is not None: + headers.append(("Content-Range", f"{self.units} */{self.length}")) + return headers + + +class ExpectationFailed(HTTPException): + """*417* `Expectation Failed` + + The server cannot meet the requirements of the Expect request-header. + + .. versionadded:: 0.7 + """ + + code = 417 + description = "The server could not meet the requirements of the Expect header" + + +class ImATeapot(HTTPException): + """*418* `I'm a teapot` + + The server should return this if it is a teapot and someone attempted + to brew coffee with it. + + .. versionadded:: 0.7 + """ + + code = 418 + description = "This server is a teapot, not a coffee machine" + + +class UnprocessableEntity(HTTPException): + """*422* `Unprocessable Entity` + + Used if the request is well formed, but the instructions are otherwise + incorrect. + """ + + code = 422 + description = ( + "The request was well-formed but was unable to be followed due" + " to semantic errors." + ) + + +class Locked(HTTPException): + """*423* `Locked` + + Used if the resource that is being accessed is locked. + """ + + code = 423 + description = "The resource that is being accessed is locked." + + +class FailedDependency(HTTPException): + """*424* `Failed Dependency` + + Used if the method could not be performed on the resource + because the requested action depended on another action and that action failed. + """ + + code = 424 + description = ( + "The method could not be performed on the resource because the" + " requested action depended on another action and that action" + " failed." + ) + + +class PreconditionRequired(HTTPException): + """*428* `Precondition Required` + + The server requires this request to be conditional, typically to prevent + the lost update problem, which is a race condition between two or more + clients attempting to update a resource through PUT or DELETE. By requiring + each client to include a conditional header ("If-Match" or "If-Unmodified- + Since") with the proper value retained from a recent GET request, the + server ensures that each client has at least seen the previous revision of + the resource. + """ + + code = 428 + description = ( + "This request is required to be conditional; try using" + ' "If-Match" or "If-Unmodified-Since".' + ) + + +class _RetryAfter(HTTPException): + """Adds an optional ``retry_after`` parameter which will set the + ``Retry-After`` header. May be an :class:`int` number of seconds or + a :class:`~datetime.datetime`. + """ + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + retry_after: t.Optional[t.Union[datetime, int]] = None, + ) -> None: + super().__init__(description, response) + self.retry_after = retry_after + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + + if self.retry_after: + if isinstance(self.retry_after, datetime): + from .http import http_date + + value = http_date(self.retry_after) + else: + value = str(self.retry_after) + + headers.append(("Retry-After", value)) + + return headers + + +class TooManyRequests(_RetryAfter): + """*429* `Too Many Requests` + + The server is limiting the rate at which this user receives + responses, and this request exceeds that rate. (The server may use + any convenient method to identify users and their request rates). + The server may include a "Retry-After" header to indicate how long + the user should wait before retrying. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 429 + description = "This user has exceeded an allotted request count. Try again later." + + +class RequestHeaderFieldsTooLarge(HTTPException): + """*431* `Request Header Fields Too Large` + + The server refuses to process the request because the header fields are too + large. One or more individual fields may be too large, or the set of all + headers is too large. + """ + + code = 431 + description = "One or more header fields exceeds the maximum size." + + +class UnavailableForLegalReasons(HTTPException): + """*451* `Unavailable For Legal Reasons` + + This status code indicates that the server is denying access to the + resource as a consequence of a legal demand. + """ + + code = 451 + description = "Unavailable for legal reasons." + + +class InternalServerError(HTTPException): + """*500* `Internal Server Error` + + Raise if an internal server error occurred. This is a good fallback if an + unknown error occurred in the dispatcher. + + .. versionchanged:: 1.0.0 + Added the :attr:`original_exception` attribute. + """ + + code = 500 + description = ( + "The server encountered an internal error and was unable to" + " complete your request. Either the server is overloaded or" + " there is an error in the application." + ) + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + original_exception: t.Optional[BaseException] = None, + ) -> None: + #: The original exception that caused this 500 error. Can be + #: used by frameworks to provide context when handling + #: unexpected errors. + self.original_exception = original_exception + super().__init__(description=description, response=response) + + +class NotImplemented(HTTPException): + """*501* `Not Implemented` + + Raise if the application does not support the action requested by the + browser. + """ + + code = 501 + description = "The server does not support the action requested by the browser." + + +class BadGateway(HTTPException): + """*502* `Bad Gateway` + + If you do proxying in your application you should return this status code + if you received an invalid response from the upstream server it accessed + in attempting to fulfill the request. + """ + + code = 502 + description = ( + "The proxy server received an invalid response from an upstream server." + ) + + +class ServiceUnavailable(_RetryAfter): + """*503* `Service Unavailable` + + Status code you should return if a service is temporarily + unavailable. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 503 + description = ( + "The server is temporarily unable to service your request due" + " to maintenance downtime or capacity problems. Please try" + " again later." + ) + + +class GatewayTimeout(HTTPException): + """*504* `Gateway Timeout` + + Status code you should return if a connection to an upstream server + times out. + """ + + code = 504 + description = "The connection to an upstream server timed out." + + +class HTTPVersionNotSupported(HTTPException): + """*505* `HTTP Version Not Supported` + + The server does not support the HTTP protocol version used in the request. + """ + + code = 505 + description = ( + "The server does not support the HTTP protocol version used in the request." + ) + + +default_exceptions: t.Dict[int, t.Type[HTTPException]] = {} + + +def _find_exceptions() -> None: + for obj in globals().values(): + try: + is_http_exception = issubclass(obj, HTTPException) + except TypeError: + is_http_exception = False + if not is_http_exception or obj.code is None: + continue + old_obj = default_exceptions.get(obj.code, None) + if old_obj is not None and issubclass(obj, old_obj): + continue + default_exceptions[obj.code] = obj + + +_find_exceptions() +del _find_exceptions + + +class Aborter: + """When passed a dict of code -> exception items it can be used as + callable that raises exceptions. If the first argument to the + callable is an integer it will be looked up in the mapping, if it's + a WSGI application it will be raised in a proxy exception. + + The rest of the arguments are forwarded to the exception constructor. + """ + + def __init__( + self, + mapping: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, + extra: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, + ) -> None: + if mapping is None: + mapping = default_exceptions + self.mapping = dict(mapping) + if extra is not None: + self.mapping.update(extra) + + def __call__( + self, code: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any + ) -> "te.NoReturn": + from .sansio.response import Response + + if isinstance(code, Response): + raise HTTPException(response=code) + + if code not in self.mapping: + raise LookupError(f"no exception for {code!r}") + + raise self.mapping[code](*args, **kwargs) + + +def abort( + status: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any +) -> "te.NoReturn": + """Raises an :py:exc:`HTTPException` for the given status code or WSGI + application. + + If a status code is given, it will be looked up in the list of + exceptions and will raise that exception. If passed a WSGI application, + it will wrap it in a proxy WSGI exception and raise that:: + + abort(404) # 404 Not Found + abort(Response('Hello World')) + + """ + _aborter(status, *args, **kwargs) + + +_aborter: Aborter = Aborter() diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/formparser.py b/axios-example/lib/python3.10/site-packages/werkzeug/formparser.py new file mode 100644 index 0000000..10d58ca --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/formparser.py @@ -0,0 +1,455 @@ +import typing as t +from functools import update_wrapper +from io import BytesIO +from itertools import chain +from typing import Union + +from . import exceptions +from .datastructures import FileStorage +from .datastructures import Headers +from .datastructures import MultiDict +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartDecoder +from .sansio.multipart import NeedData +from .urls import url_decode_stream +from .wsgi import _make_chunk_iter +from .wsgi import get_content_length +from .wsgi import get_input_stream + +# there are some platforms where SpooledTemporaryFile is not available. +# In that case we need to provide a fallback. +try: + from tempfile import SpooledTemporaryFile +except ImportError: + from tempfile import TemporaryFile + + SpooledTemporaryFile = None # type: ignore + +if t.TYPE_CHECKING: + import typing as te + from _typeshed.wsgi import WSGIEnvironment + + t_parse_result = t.Tuple[t.IO[bytes], MultiDict, MultiDict] + + class TStreamFactory(te.Protocol): + def __call__( + self, + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str], + content_length: t.Optional[int] = None, + ) -> t.IO[bytes]: + ... + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def _exhaust(stream: t.IO[bytes]) -> None: + bts = stream.read(64 * 1024) + while bts: + bts = stream.read(64 * 1024) + + +def default_stream_factory( + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str], + content_length: t.Optional[int] = None, +) -> t.IO[bytes]: + max_size = 1024 * 500 + + if SpooledTemporaryFile is not None: + return t.cast(t.IO[bytes], SpooledTemporaryFile(max_size=max_size, mode="rb+")) + elif total_content_length is None or total_content_length > max_size: + return t.cast(t.IO[bytes], TemporaryFile("rb+")) + + return BytesIO() + + +def parse_form_data( + environ: "WSGIEnvironment", + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + max_content_length: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + silent: bool = True, +) -> "t_parse_result": + """Parse the form data in the environ and return it as tuple in the form + ``(stream, form, files)``. You should only call this method if the + transport method is `POST`, `PUT`, or `PATCH`. + + If the mimetype of the data transmitted is `multipart/form-data` the + files multidict will be filled with `FileStorage` objects. If the + mimetype is unknown the input stream is wrapped and returned as first + argument, else the stream is empty. + + This is a shortcut for the common usage of :class:`FormDataParser`. + + Have a look at :doc:`/request_data` for more details. + + .. versionadded:: 0.5 + The `max_form_memory_size`, `max_content_length` and + `cls` parameters were added. + + .. versionadded:: 0.5.1 + The optional `silent` flag was added. + + :param environ: the WSGI environment to be used for parsing. + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :return: A tuple in the form ``(stream, form, files)``. + """ + return FormDataParser( + stream_factory, + charset, + errors, + max_form_memory_size, + max_content_length, + cls, + silent, + ).parse_from_environ(environ) + + +def exhaust_stream(f: F) -> F: + """Helper decorator for methods that exhausts the stream on return.""" + + def wrapper(self, stream, *args, **kwargs): # type: ignore + try: + return f(self, stream, *args, **kwargs) + finally: + exhaust = getattr(stream, "exhaust", None) + + if exhaust is not None: + exhaust() + else: + while True: + chunk = stream.read(1024 * 64) + + if not chunk: + break + + return update_wrapper(t.cast(F, wrapper), f) + + +class FormDataParser: + """This class implements parsing of form data for Werkzeug. By itself + it can parse multipart and url encoded form data. It can be subclassed + and extended but for most mimetypes it is a better idea to use the + untouched stream and expose it as separate attributes on a request + object. + + .. versionadded:: 0.8 + + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + """ + + def __init__( + self, + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + max_content_length: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + silent: bool = True, + ) -> None: + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + self.max_content_length = max_content_length + + if cls is None: + cls = MultiDict + + self.cls = cls + self.silent = silent + + def get_parse_func( + self, mimetype: str, options: t.Dict[str, str] + ) -> t.Optional[ + t.Callable[ + ["FormDataParser", t.IO[bytes], str, t.Optional[int], t.Dict[str, str]], + "t_parse_result", + ] + ]: + return self.parse_functions.get(mimetype) + + def parse_from_environ(self, environ: "WSGIEnvironment") -> "t_parse_result": + """Parses the information from the environment as form data. + + :param environ: the WSGI environment to be used for parsing. + :return: A tuple in the form ``(stream, form, files)``. + """ + content_type = environ.get("CONTENT_TYPE", "") + content_length = get_content_length(environ) + mimetype, options = parse_options_header(content_type) + return self.parse(get_input_stream(environ), mimetype, content_length, options) + + def parse( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Optional[t.Dict[str, str]] = None, + ) -> "t_parse_result": + """Parses the information from the given stream, mimetype, + content length and mimetype parameters. + + :param stream: an input stream + :param mimetype: the mimetype of the data + :param content_length: the content length of the incoming data + :param options: optional mimetype parameters (used for + the multipart boundary for instance) + :return: A tuple in the form ``(stream, form, files)``. + """ + if ( + self.max_content_length is not None + and content_length is not None + and content_length > self.max_content_length + ): + # if the input stream is not exhausted, firefox reports Connection Reset + _exhaust(stream) + raise exceptions.RequestEntityTooLarge() + + if options is None: + options = {} + + parse_func = self.get_parse_func(mimetype, options) + + if parse_func is not None: + try: + return parse_func(self, stream, mimetype, content_length, options) + except ValueError: + if not self.silent: + raise + + return stream, self.cls(), self.cls() + + @exhaust_stream + def _parse_multipart( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Dict[str, str], + ) -> "t_parse_result": + parser = MultiPartParser( + self.stream_factory, + self.charset, + self.errors, + max_form_memory_size=self.max_form_memory_size, + cls=self.cls, + ) + boundary = options.get("boundary", "").encode("ascii") + + if not boundary: + raise ValueError("Missing boundary") + + form, files = parser.parse(stream, boundary, content_length) + return stream, form, files + + @exhaust_stream + def _parse_urlencoded( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Dict[str, str], + ) -> "t_parse_result": + if ( + self.max_form_memory_size is not None + and content_length is not None + and content_length > self.max_form_memory_size + ): + # if the input stream is not exhausted, firefox reports Connection Reset + _exhaust(stream) + raise exceptions.RequestEntityTooLarge() + + form = url_decode_stream(stream, self.charset, errors=self.errors, cls=self.cls) + return stream, form, self.cls() + + #: mapping of mimetypes to parsing functions + parse_functions: t.Dict[ + str, + t.Callable[ + ["FormDataParser", t.IO[bytes], str, t.Optional[int], t.Dict[str, str]], + "t_parse_result", + ], + ] = { + "multipart/form-data": _parse_multipart, + "application/x-www-form-urlencoded": _parse_urlencoded, + "application/x-url-encoded": _parse_urlencoded, + } + + +def _line_parse(line: str) -> t.Tuple[str, bool]: + """Removes line ending characters and returns a tuple (`stripped_line`, + `is_terminated`). + """ + if line[-2:] == "\r\n": + return line[:-2], True + + elif line[-1:] in {"\r", "\n"}: + return line[:-1], True + + return line, False + + +class MultiPartParser: + def __init__( + self, + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + buffer_size: int = 64 * 1024, + ) -> None: + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + + if cls is None: + cls = MultiDict + + self.cls = cls + + self.buffer_size = buffer_size + + def fail(self, message: str) -> "te.NoReturn": + raise ValueError(message) + + def get_part_charset(self, headers: Headers) -> str: + # Figure out input charset for current part + content_type = headers.get("content-type") + + if content_type: + mimetype, ct_params = parse_options_header(content_type) + return ct_params.get("charset", self.charset) + + return self.charset + + def start_file_streaming( + self, event: File, total_content_length: t.Optional[int] + ) -> t.IO[bytes]: + content_type = event.headers.get("content-type") + + try: + content_length = int(event.headers["content-length"]) + except (KeyError, ValueError): + content_length = 0 + + container = self.stream_factory( + total_content_length=total_content_length, + filename=event.filename, + content_type=content_type, + content_length=content_length, + ) + return container + + def parse( + self, stream: t.IO[bytes], boundary: bytes, content_length: t.Optional[int] + ) -> t.Tuple[MultiDict, MultiDict]: + container: t.Union[t.IO[bytes], t.List[bytes]] + _write: t.Callable[[bytes], t.Any] + + iterator = chain( + _make_chunk_iter( + stream, + limit=content_length, + buffer_size=self.buffer_size, + ), + [None], + ) + + parser = MultipartDecoder(boundary, self.max_form_memory_size) + + fields = [] + files = [] + + current_part: Union[Field, File] + for data in iterator: + parser.receive_data(data) + event = parser.next_event() + while not isinstance(event, (Epilogue, NeedData)): + if isinstance(event, Field): + current_part = event + container = [] + _write = container.append + elif isinstance(event, File): + current_part = event + container = self.start_file_streaming(event, content_length) + _write = container.write + elif isinstance(event, Data): + _write(event.data) + if not event.more_data: + if isinstance(current_part, Field): + value = b"".join(container).decode( + self.get_part_charset(current_part.headers), self.errors + ) + fields.append((current_part.name, value)) + else: + container = t.cast(t.IO[bytes], container) + container.seek(0) + files.append( + ( + current_part.name, + FileStorage( + container, + current_part.filename, + current_part.name, + headers=current_part.headers, + ), + ) + ) + + event = parser.next_event() + + return self.cls(fields), self.cls(files) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/http.py b/axios-example/lib/python3.10/site-packages/werkzeug/http.py new file mode 100644 index 0000000..9369900 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/http.py @@ -0,0 +1,1371 @@ +import base64 +import email.utils +import re +import typing +import typing as t +import warnings +from datetime import date +from datetime import datetime +from datetime import time +from datetime import timedelta +from datetime import timezone +from enum import Enum +from hashlib import sha1 +from time import mktime +from time import struct_time +from urllib.parse import unquote_to_bytes as _unquote +from urllib.request import parse_http_list as _parse_list_header + +from ._internal import _cookie_parse_impl +from ._internal import _cookie_quote +from ._internal import _make_cookie_domain +from ._internal import _to_bytes +from ._internal import _to_str +from ._internal import _wsgi_decoding_dance +from werkzeug._internal import _dt_as_utc + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIEnvironment + +# for explanation of "media-range", etc. see Sections 5.3.{1,2} of RFC 7231 +_accept_re = re.compile( + r""" + ( # media-range capturing-parenthesis + [^\s;,]+ # type/subtype + (?:[ \t]*;[ \t]* # ";" + (?: # parameter non-capturing-parenthesis + [^\s;,q][^\s;,]* # token that doesn't start with "q" + | # or + q[^\s;,=][^\s;,]* # token that is more than just "q" + ) + )* # zero or more parameters + ) # end of media-range + (?:[ \t]*;[ \t]*q= # weight is a "q" parameter + (\d*(?:\.\d+)?) # qvalue capturing-parentheses + [^,]* # "extension" accept params: who cares? + )? # accept params are optional + """, + re.VERBOSE, +) +_token_chars = frozenset( + "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~" +) +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') +_option_header_piece_re = re.compile( + r""" + ;\s*,?\s* # newlines were replaced with commas + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^\s;,=*]+ # token + ) + (?:\*(?P\d+))? # *1, optional continuation index + \s* + (?: # optionally followed by =value + (?: # equals sign, possibly with encoding + \*\s*=\s* # * indicates extended notation + (?: # optional encoding + (?P[^\s]+?) + '(?P[^\s]*?)' + )? + | + =\s* # basic notation + ) + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^;,]+ # token + )? + )? + \s* + """, + flags=re.VERBOSE, +) +_option_header_start_mime_type = re.compile(r",\s*([^;,\s]+)([;,]\s*.+)?") +_entity_headers = frozenset( + [ + "allow", + "content-encoding", + "content-language", + "content-length", + "content-location", + "content-md5", + "content-range", + "content-type", + "expires", + "last-modified", + ] +) +_hop_by_hop_headers = frozenset( + [ + "connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ] +) +HTTP_STATUS_CODES = { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 103: "Early Hints", # see RFC 8297 + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi Status", + 208: "Already Reported", # see RFC 5842 + 226: "IM Used", # see RFC 3229 + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Switch Proxy", # unused + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", # unused + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 418: "I'm a teapot", # see RFC 2324 + 421: "Misdirected Request", # see RFC 7540 + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Too Early", # see RFC 8470 + 426: "Upgrade Required", + 428: "Precondition Required", # see RFC 6585 + 429: "Too Many Requests", + 431: "Request Header Fields Too Large", + 449: "Retry With", # proprietary MS extension + 451: "Unavailable For Legal Reasons", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates", # see RFC 2295 + 507: "Insufficient Storage", + 508: "Loop Detected", # see RFC 5842 + 510: "Not Extended", + 511: "Network Authentication Failed", +} + + +class COEP(Enum): + """Cross Origin Embedder Policies""" + + UNSAFE_NONE = "unsafe-none" + REQUIRE_CORP = "require-corp" + + +class COOP(Enum): + """Cross Origin Opener Policies""" + + UNSAFE_NONE = "unsafe-none" + SAME_ORIGIN_ALLOW_POPUPS = "same-origin-allow-popups" + SAME_ORIGIN = "same-origin" + + +def quote_header_value( + value: t.Union[str, int], extra_chars: str = "", allow_token: bool = True +) -> str: + """Quote a header value if necessary. + + .. versionadded:: 0.5 + + :param value: the value to quote. + :param extra_chars: a list of extra characters to skip quoting. + :param allow_token: if this is enabled token values are returned + unchanged. + """ + if isinstance(value, bytes): + value = value.decode("latin1") + value = str(value) + if allow_token: + token_chars = _token_chars | set(extra_chars) + if set(value).issubset(token_chars): + return value + value = value.replace("\\", "\\\\").replace('"', '\\"') + return f'"{value}"' + + +def unquote_header_value(value: str, is_filename: bool = False) -> str: + r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). + This does not use the real unquoting but what browsers are actually + using for quoting. + + .. versionadded:: 0.5 + + :param value: the header value to unquote. + :param is_filename: The value represents a filename or path. + """ + if value and value[0] == value[-1] == '"': + # this is not the real unquoting, but fixing this so that the + # RFC is met will result in bugs with internet explorer and + # probably some other browsers as well. IE for example is + # uploading files with "C:\foo\bar.txt" as filename + value = value[1:-1] + + # if this is a filename and the starting characters look like + # a UNC path, then just return the value without quotes. Using the + # replace sequence below on a UNC path has the effect of turning + # the leading double slash into a single slash and then + # _fix_ie_filename() doesn't work correctly. See #458. + if not is_filename or value[:2] != "\\\\": + return value.replace("\\\\", "\\").replace('\\"', '"') + return value + + +def dump_options_header( + header: t.Optional[str], options: t.Mapping[str, t.Optional[t.Union[str, int]]] +) -> str: + """The reverse function to :func:`parse_options_header`. + + :param header: the header to dump + :param options: a dict of options to append. + """ + segments = [] + if header is not None: + segments.append(header) + for key, value in options.items(): + if value is None: + segments.append(key) + else: + segments.append(f"{key}={quote_header_value(value)}") + return "; ".join(segments) + + +def dump_header( + iterable: t.Union[t.Dict[str, t.Union[str, int]], t.Iterable[str]], + allow_token: bool = True, +) -> str: + """Dump an HTTP header again. This is the reversal of + :func:`parse_list_header`, :func:`parse_set_header` and + :func:`parse_dict_header`. This also quotes strings that include an + equals sign unless you pass it as dict of key, value pairs. + + >>> dump_header({'foo': 'bar baz'}) + 'foo="bar baz"' + >>> dump_header(('foo', 'bar baz')) + 'foo, "bar baz"' + + :param iterable: the iterable or dict of values to quote. + :param allow_token: if set to `False` tokens as values are disallowed. + See :func:`quote_header_value` for more details. + """ + if isinstance(iterable, dict): + items = [] + for key, value in iterable.items(): + if value is None: + items.append(key) + else: + items.append( + f"{key}={quote_header_value(value, allow_token=allow_token)}" + ) + else: + items = [quote_header_value(x, allow_token=allow_token) for x in iterable] + return ", ".join(items) + + +def dump_csp_header(header: "ds.ContentSecurityPolicy") -> str: + """Dump a Content Security Policy header. + + These are structured into policies such as "default-src 'self'; + script-src 'self'". + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + """ + return "; ".join(f"{key} {value}" for key, value in header.items()) + + +def parse_list_header(value: str) -> t.List[str]: + """Parse lists as described by RFC 2068 Section 2. + + In particular, parse comma-separated lists where the elements of + the list may include quoted-strings. A quoted-string could + contain a comma. A non-quoted string could have quotes in the + middle. Quotes are removed automatically after parsing. + + It basically works like :func:`parse_set_header` just that items + may appear multiple times and case sensitivity is preserved. + + The return value is a standard :class:`list`: + + >>> parse_list_header('token, "quoted value"') + ['token', 'quoted value'] + + To create a header from the :class:`list` again, use the + :func:`dump_header` function. + + :param value: a string with a list header. + :return: :class:`list` + """ + result = [] + for item in _parse_list_header(value): + if item[:1] == item[-1:] == '"': + item = unquote_header_value(item[1:-1]) + result.append(item) + return result + + +def parse_dict_header(value: str, cls: t.Type[dict] = dict) -> t.Dict[str, str]: + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict (or any other mapping object created from + the type with a dict like interface provided by the `cls` argument): + + >>> d = parse_dict_header('foo="is a fish", bar="as well"') + >>> type(d) is dict + True + >>> sorted(d.items()) + [('bar', 'as well'), ('foo', 'is a fish')] + + If there is no value for a key it will be `None`: + + >>> parse_dict_header('key_without_value') + {'key_without_value': None} + + To create a header from the :class:`dict` again, use the + :func:`dump_header` function. + + .. versionchanged:: 0.9 + Added support for `cls` argument. + + :param value: a string with a dict header. + :param cls: callable to use for storage of parsed results. + :return: an instance of `cls` + """ + result = cls() + if isinstance(value, bytes): + value = value.decode("latin1") + for item in _parse_list_header(value): + if "=" not in item: + result[item] = None + continue + name, value = item.split("=", 1) + if value[:1] == value[-1:] == '"': + value = unquote_header_value(value[1:-1]) + result[name] = value + return result + + +def parse_options_header( + value: t.Optional[str], multiple: "te.Literal[None]" = None +) -> t.Tuple[str, t.Dict[str, str]]: + """Parse a ``Content-Type``-like header into a tuple with the + value and any options: + + >>> parse_options_header('text/html; charset=utf8') + ('text/html', {'charset': 'utf8'}) + + This should is not for ``Cache-Control``-like headers, which use a + different format. For those, use :func:`parse_dict_header`. + + :param value: The header value to parse. + + .. versionchanged:: 2.1 + The ``multiple`` parameter is deprecated and will be removed in + Werkzeug 2.2. + + .. versionchanged:: 0.15 + :rfc:`2231` parameter continuations are handled. + + .. versionadded:: 0.5 + """ + if multiple is not None: + import warnings + + warnings.warn( + "The 'multiple' parameter of 'parse_options_header' is" + " deprecated and will be removed in Werkzeug 2.2.", + DeprecationWarning, + stacklevel=2, + ) + + if not value: + return "", {} + + result: t.List[t.Any] = [] + + value = "," + value.replace("\n", ",") + while value: + match = _option_header_start_mime_type.match(value) + if not match: + break + result.append(match.group(1)) # mimetype + options: t.Dict[str, str] = {} + # Parse options + rest = match.group(2) + encoding: t.Optional[str] + continued_encoding: t.Optional[str] = None + while rest: + optmatch = _option_header_piece_re.match(rest) + if not optmatch: + break + option, count, encoding, language, option_value = optmatch.groups() + # Continuations don't have to supply the encoding after the + # first line. If we're in a continuation, track the current + # encoding to use for subsequent lines. Reset it when the + # continuation ends. + if not count: + continued_encoding = None + else: + if not encoding: + encoding = continued_encoding + continued_encoding = encoding + option = unquote_header_value(option) + + if option_value is not None: + option_value = unquote_header_value(option_value, option == "filename") + + if encoding is not None: + option_value = _unquote(option_value).decode(encoding) + + if count: + # Continuations append to the existing value. For + # simplicity, this ignores the possibility of + # out-of-order indices, which shouldn't happen anyway. + if option_value is not None: + options[option] = options.get(option, "") + option_value + else: + options[option] = option_value # type: ignore[assignment] + + rest = rest[optmatch.end() :] + result.append(options) + if not multiple: + return tuple(result) # type: ignore[return-value] + value = rest + + return tuple(result) if result else ("", {}) # type: ignore[return-value] + + +_TAnyAccept = t.TypeVar("_TAnyAccept", bound="ds.Accept") + + +@typing.overload +def parse_accept_header(value: t.Optional[str]) -> "ds.Accept": + ... + + +@typing.overload +def parse_accept_header( + value: t.Optional[str], cls: t.Type[_TAnyAccept] +) -> _TAnyAccept: + ... + + +def parse_accept_header( + value: t.Optional[str], cls: t.Optional[t.Type[_TAnyAccept]] = None +) -> _TAnyAccept: + """Parses an HTTP Accept-* header. This does not implement a complete + valid algorithm but one that supports at least value and quality + extraction. + + Returns a new :class:`Accept` object (basically a list of ``(value, quality)`` + tuples sorted by the quality with some additional accessor methods). + + The second parameter can be a subclass of :class:`Accept` that is created + with the parsed values and returned. + + :param value: the accept header string to be parsed. + :param cls: the wrapper class for the return value (can be + :class:`Accept` or a subclass thereof) + :return: an instance of `cls`. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyAccept], ds.Accept) + + if not value: + return cls(None) + + result = [] + for match in _accept_re.finditer(value): + quality_match = match.group(2) + if not quality_match: + quality: float = 1 + else: + quality = max(min(float(quality_match), 1), 0) + result.append((match.group(1), quality)) + return cls(result) + + +_TAnyCC = t.TypeVar("_TAnyCC", bound="ds._CacheControl") +_t_cc_update = t.Optional[t.Callable[[_TAnyCC], None]] + + +@typing.overload +def parse_cache_control_header( + value: t.Optional[str], on_update: _t_cc_update, cls: None = None +) -> "ds.RequestCacheControl": + ... + + +@typing.overload +def parse_cache_control_header( + value: t.Optional[str], on_update: _t_cc_update, cls: t.Type[_TAnyCC] +) -> _TAnyCC: + ... + + +def parse_cache_control_header( + value: t.Optional[str], + on_update: _t_cc_update = None, + cls: t.Optional[t.Type[_TAnyCC]] = None, +) -> _TAnyCC: + """Parse a cache control header. The RFC differs between response and + request cache control, this method does not. It's your responsibility + to not use the wrong control statements. + + .. versionadded:: 0.5 + The `cls` was added. If not specified an immutable + :class:`~werkzeug.datastructures.RequestCacheControl` is returned. + + :param value: a cache control header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.CacheControl` + object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.RequestCacheControl` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyCC], ds.RequestCacheControl) + + if not value: + return cls((), on_update) + + return cls(parse_dict_header(value), on_update) + + +_TAnyCSP = t.TypeVar("_TAnyCSP", bound="ds.ContentSecurityPolicy") +_t_csp_update = t.Optional[t.Callable[[_TAnyCSP], None]] + + +@typing.overload +def parse_csp_header( + value: t.Optional[str], on_update: _t_csp_update, cls: None = None +) -> "ds.ContentSecurityPolicy": + ... + + +@typing.overload +def parse_csp_header( + value: t.Optional[str], on_update: _t_csp_update, cls: t.Type[_TAnyCSP] +) -> _TAnyCSP: + ... + + +def parse_csp_header( + value: t.Optional[str], + on_update: _t_csp_update = None, + cls: t.Optional[t.Type[_TAnyCSP]] = None, +) -> _TAnyCSP: + """Parse a Content Security Policy header. + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + :param value: a csp header to be parsed. + :param on_update: an optional callable that is called every time a value + on the object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.ContentSecurityPolicy` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyCSP], ds.ContentSecurityPolicy) + + if value is None: + return cls((), on_update) + + items = [] + + for policy in value.split(";"): + policy = policy.strip() + + # Ignore badly formatted policies (no space) + if " " in policy: + directive, value = policy.strip().split(" ", 1) + items.append((directive.strip(), value.strip())) + + return cls(items, on_update) + + +def parse_set_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.HeaderSet"], None]] = None, +) -> "ds.HeaderSet": + """Parse a set-like header and return a + :class:`~werkzeug.datastructures.HeaderSet` object: + + >>> hs = parse_set_header('token, "quoted value"') + + The return value is an object that treats the items case-insensitively + and keeps the order of the items: + + >>> 'TOKEN' in hs + True + >>> hs.index('quoted value') + 1 + >>> hs + HeaderSet(['token', 'quoted value']) + + To create a header from the :class:`HeaderSet` again, use the + :func:`dump_header` function. + + :param value: a set header to be parsed. + :param on_update: an optional callable that is called every time a + value on the :class:`~werkzeug.datastructures.HeaderSet` + object is changed. + :return: a :class:`~werkzeug.datastructures.HeaderSet` + """ + if not value: + return ds.HeaderSet(None, on_update) + return ds.HeaderSet(parse_list_header(value), on_update) + + +def parse_authorization_header( + value: t.Optional[str], +) -> t.Optional["ds.Authorization"]: + """Parse an HTTP basic/digest authorization header transmitted by the web + browser. The return value is either `None` if the header was invalid or + not given, otherwise an :class:`~werkzeug.datastructures.Authorization` + object. + + :param value: the authorization header to parse. + :return: a :class:`~werkzeug.datastructures.Authorization` object or `None`. + """ + if not value: + return None + value = _wsgi_decoding_dance(value) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except ValueError: + return None + if auth_type == "basic": + try: + username, password = base64.b64decode(auth_info).split(b":", 1) + except Exception: + return None + try: + return ds.Authorization( + "basic", + { + "username": _to_str(username, "utf-8"), + "password": _to_str(password, "utf-8"), + }, + ) + except UnicodeDecodeError: + return None + elif auth_type == "digest": + auth_map = parse_dict_header(auth_info) + for key in "username", "realm", "nonce", "uri", "response": + if key not in auth_map: + return None + if "qop" in auth_map: + if not auth_map.get("nc") or not auth_map.get("cnonce"): + return None + return ds.Authorization("digest", auth_map) + return None + + +def parse_www_authenticate_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.WWWAuthenticate"], None]] = None, +) -> "ds.WWWAuthenticate": + """Parse an HTTP WWW-Authenticate header into a + :class:`~werkzeug.datastructures.WWWAuthenticate` object. + + :param value: a WWW-Authenticate header to parse. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.WWWAuthenticate` + object is changed. + :return: a :class:`~werkzeug.datastructures.WWWAuthenticate` object. + """ + if not value: + return ds.WWWAuthenticate(on_update=on_update) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except (ValueError, AttributeError): + return ds.WWWAuthenticate(value.strip().lower(), on_update=on_update) + return ds.WWWAuthenticate(auth_type, parse_dict_header(auth_info), on_update) + + +def parse_if_range_header(value: t.Optional[str]) -> "ds.IfRange": + """Parses an if-range header which can be an etag or a date. Returns + a :class:`~werkzeug.datastructures.IfRange` object. + + .. versionchanged:: 2.0 + If the value represents a datetime, it is timezone-aware. + + .. versionadded:: 0.7 + """ + if not value: + return ds.IfRange() + date = parse_date(value) + if date is not None: + return ds.IfRange(date=date) + # drop weakness information + return ds.IfRange(unquote_etag(value)[0]) + + +def parse_range_header( + value: t.Optional[str], make_inclusive: bool = True +) -> t.Optional["ds.Range"]: + """Parses a range header into a :class:`~werkzeug.datastructures.Range` + object. If the header is missing or malformed `None` is returned. + `ranges` is a list of ``(start, stop)`` tuples where the ranges are + non-inclusive. + + .. versionadded:: 0.7 + """ + if not value or "=" not in value: + return None + + ranges = [] + last_end = 0 + units, rng = value.split("=", 1) + units = units.strip().lower() + + for item in rng.split(","): + item = item.strip() + if "-" not in item: + return None + if item.startswith("-"): + if last_end < 0: + return None + try: + begin = int(item) + except ValueError: + return None + end = None + last_end = -1 + elif "-" in item: + begin_str, end_str = item.split("-", 1) + begin_str = begin_str.strip() + end_str = end_str.strip() + if not begin_str.isdigit(): + return None + begin = int(begin_str) + if begin < last_end or last_end < 0: + return None + if end_str: + if not end_str.isdigit(): + return None + end = int(end_str) + 1 + if begin >= end: + return None + else: + end = None + last_end = end if end is not None else -1 + ranges.append((begin, end)) + + return ds.Range(units, ranges) + + +def parse_content_range_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.ContentRange"], None]] = None, +) -> t.Optional["ds.ContentRange"]: + """Parses a range header into a + :class:`~werkzeug.datastructures.ContentRange` object or `None` if + parsing is not possible. + + .. versionadded:: 0.7 + + :param value: a content range header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.ContentRange` + object is changed. + """ + if value is None: + return None + try: + units, rangedef = (value or "").strip().split(None, 1) + except ValueError: + return None + + if "/" not in rangedef: + return None + rng, length_str = rangedef.split("/", 1) + if length_str == "*": + length = None + elif length_str.isdigit(): + length = int(length_str) + else: + return None + + if rng == "*": + return ds.ContentRange(units, None, None, length, on_update=on_update) + elif "-" not in rng: + return None + + start_str, stop_str = rng.split("-", 1) + try: + start = int(start_str) + stop = int(stop_str) + 1 + except ValueError: + return None + + if is_byte_range_valid(start, stop, length): + return ds.ContentRange(units, start, stop, length, on_update=on_update) + + return None + + +def quote_etag(etag: str, weak: bool = False) -> str: + """Quote an etag. + + :param etag: the etag to quote. + :param weak: set to `True` to tag it "weak". + """ + if '"' in etag: + raise ValueError("invalid etag") + etag = f'"{etag}"' + if weak: + etag = f"W/{etag}" + return etag + + +def unquote_etag( + etag: t.Optional[str], +) -> t.Union[t.Tuple[str, bool], t.Tuple[None, None]]: + """Unquote a single etag: + + >>> unquote_etag('W/"bar"') + ('bar', True) + >>> unquote_etag('"bar"') + ('bar', False) + + :param etag: the etag identifier to unquote. + :return: a ``(etag, weak)`` tuple. + """ + if not etag: + return None, None + etag = etag.strip() + weak = False + if etag.startswith(("W/", "w/")): + weak = True + etag = etag[2:] + if etag[:1] == etag[-1:] == '"': + etag = etag[1:-1] + return etag, weak + + +def parse_etags(value: t.Optional[str]) -> "ds.ETags": + """Parse an etag header. + + :param value: the tag header to parse + :return: an :class:`~werkzeug.datastructures.ETags` object. + """ + if not value: + return ds.ETags() + strong = [] + weak = [] + end = len(value) + pos = 0 + while pos < end: + match = _etag_re.match(value, pos) + if match is None: + break + is_weak, quoted, raw = match.groups() + if raw == "*": + return ds.ETags(star_tag=True) + elif quoted: + raw = quoted + if is_weak: + weak.append(raw) + else: + strong.append(raw) + pos = match.end() + return ds.ETags(strong, weak) + + +def generate_etag(data: bytes) -> str: + """Generate an etag for some data. + + .. versionchanged:: 2.0 + Use SHA-1. MD5 may not be available in some environments. + """ + return sha1(data).hexdigest() + + +def parse_date(value: t.Optional[str]) -> t.Optional[datetime]: + """Parse an :rfc:`2822` date into a timezone-aware + :class:`datetime.datetime` object, or ``None`` if parsing fails. + + This is a wrapper for :func:`email.utils.parsedate_to_datetime`. It + returns ``None`` if parsing fails instead of raising an exception, + and always returns a timezone-aware datetime object. If the string + doesn't have timezone information, it is assumed to be UTC. + + :param value: A string with a supported date format. + + .. versionchanged:: 2.0 + Return a timezone-aware datetime object. Use + ``email.utils.parsedate_to_datetime``. + """ + if value is None: + return None + + try: + dt = email.utils.parsedate_to_datetime(value) + except (TypeError, ValueError): + return None + + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + + return dt + + +def http_date( + timestamp: t.Optional[t.Union[datetime, date, int, float, struct_time]] = None +) -> str: + """Format a datetime object or timestamp into an :rfc:`2822` date + string. + + This is a wrapper for :func:`email.utils.format_datetime`. It + assumes naive datetime objects are in UTC instead of raising an + exception. + + :param timestamp: The datetime or timestamp to format. Defaults to + the current time. + + .. versionchanged:: 2.0 + Use ``email.utils.format_datetime``. Accept ``date`` objects. + """ + if isinstance(timestamp, date): + if not isinstance(timestamp, datetime): + # Assume plain date is midnight UTC. + timestamp = datetime.combine(timestamp, time(), tzinfo=timezone.utc) + else: + # Ensure datetime is timezone-aware. + timestamp = _dt_as_utc(timestamp) + + return email.utils.format_datetime(timestamp, usegmt=True) + + if isinstance(timestamp, struct_time): + timestamp = mktime(timestamp) + + return email.utils.formatdate(timestamp, usegmt=True) + + +def parse_age(value: t.Optional[str] = None) -> t.Optional[timedelta]: + """Parses a base-10 integer count of seconds into a timedelta. + + If parsing fails, the return value is `None`. + + :param value: a string consisting of an integer represented in base-10 + :return: a :class:`datetime.timedelta` object or `None`. + """ + if not value: + return None + try: + seconds = int(value) + except ValueError: + return None + if seconds < 0: + return None + try: + return timedelta(seconds=seconds) + except OverflowError: + return None + + +def dump_age(age: t.Optional[t.Union[timedelta, int]] = None) -> t.Optional[str]: + """Formats the duration as a base-10 integer. + + :param age: should be an integer number of seconds, + a :class:`datetime.timedelta` object, or, + if the age is unknown, `None` (default). + """ + if age is None: + return None + if isinstance(age, timedelta): + age = int(age.total_seconds()) + else: + age = int(age) + + if age < 0: + raise ValueError("age cannot be negative") + + return str(age) + + +def is_resource_modified( + environ: "WSGIEnvironment", + etag: t.Optional[str] = None, + data: t.Optional[bytes] = None, + last_modified: t.Optional[t.Union[datetime, str]] = None, + ignore_if_range: bool = True, +) -> bool: + """Convenience method for conditional requests. + + :param environ: the WSGI environment of the request to be checked. + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + + .. versionchanged:: 2.0 + SHA-1 is used to generate an etag value for the data. MD5 may + not be available in some environments. + + .. versionchanged:: 1.0.0 + The check is run for methods other than ``GET`` and ``HEAD``. + """ + if etag is None and data is not None: + etag = generate_etag(data) + elif data is not None: + raise TypeError("both data and etag given") + + unmodified = False + if isinstance(last_modified, str): + last_modified = parse_date(last_modified) + + # HTTP doesn't use microsecond, remove it to avoid false positive + # comparisons. Mark naive datetimes as UTC. + if last_modified is not None: + last_modified = _dt_as_utc(last_modified.replace(microsecond=0)) + + if_range = None + if not ignore_if_range and "HTTP_RANGE" in environ: + # https://tools.ietf.org/html/rfc7233#section-3.2 + # A server MUST ignore an If-Range header field received in a request + # that does not contain a Range header field. + if_range = parse_if_range_header(environ.get("HTTP_IF_RANGE")) + + if if_range is not None and if_range.date is not None: + modified_since: t.Optional[datetime] = if_range.date + else: + modified_since = parse_date(environ.get("HTTP_IF_MODIFIED_SINCE")) + + if modified_since and last_modified and last_modified <= modified_since: + unmodified = True + + if etag: + etag, _ = unquote_etag(etag) + etag = t.cast(str, etag) + + if if_range is not None and if_range.etag is not None: + unmodified = parse_etags(if_range.etag).contains(etag) + else: + if_none_match = parse_etags(environ.get("HTTP_IF_NONE_MATCH")) + if if_none_match: + # https://tools.ietf.org/html/rfc7232#section-3.2 + # "A recipient MUST use the weak comparison function when comparing + # entity-tags for If-None-Match" + unmodified = if_none_match.contains_weak(etag) + + # https://tools.ietf.org/html/rfc7232#section-3.1 + # "Origin server MUST use the strong comparison function when + # comparing entity-tags for If-Match" + if_match = parse_etags(environ.get("HTTP_IF_MATCH")) + if if_match: + unmodified = not if_match.is_strong(etag) + + return not unmodified + + +def remove_entity_headers( + headers: t.Union["ds.Headers", t.List[t.Tuple[str, str]]], + allowed: t.Iterable[str] = ("expires", "content-location"), +) -> None: + """Remove all entity headers from a list or :class:`Headers` object. This + operation works in-place. `Expires` and `Content-Location` headers are + by default not removed. The reason for this is :rfc:`2616` section + 10.3.5 which specifies some entity headers that should be sent. + + .. versionchanged:: 0.5 + added `allowed` parameter. + + :param headers: a list or :class:`Headers` object. + :param allowed: a list of headers that should still be allowed even though + they are entity headers. + """ + allowed = {x.lower() for x in allowed} + headers[:] = [ + (key, value) + for key, value in headers + if not is_entity_header(key) or key.lower() in allowed + ] + + +def remove_hop_by_hop_headers( + headers: t.Union["ds.Headers", t.List[t.Tuple[str, str]]] +) -> None: + """Remove all HTTP/1.1 "Hop-by-Hop" headers from a list or + :class:`Headers` object. This operation works in-place. + + .. versionadded:: 0.5 + + :param headers: a list or :class:`Headers` object. + """ + headers[:] = [ + (key, value) for key, value in headers if not is_hop_by_hop_header(key) + ] + + +def is_entity_header(header: str) -> bool: + """Check if a header is an entity header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an entity header, `False` otherwise. + """ + return header.lower() in _entity_headers + + +def is_hop_by_hop_header(header: str) -> bool: + """Check if a header is an HTTP/1.1 "Hop-by-Hop" header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an HTTP/1.1 "Hop-by-Hop" header, `False` otherwise. + """ + return header.lower() in _hop_by_hop_headers + + +def parse_cookie( + header: t.Union["WSGIEnvironment", str, bytes, None], + charset: str = "utf-8", + errors: str = "replace", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, +) -> "ds.MultiDict[str, str]": + """Parse a cookie from a string or WSGI environ. + + The same key can be provided multiple times, the values are stored + in-order. The default :class:`MultiDict` will have the first value + first, and all values can be retrieved with + :meth:`MultiDict.getlist`. + + :param header: The cookie header as a string, or a WSGI environ dict + with a ``HTTP_COOKIE`` key. + :param charset: The charset for the cookie values. + :param errors: The error behavior for the charset decoding. + :param cls: A dict-like class to store the parsed cookies in. + Defaults to :class:`MultiDict`. + + .. versionchanged:: 1.0.0 + Returns a :class:`MultiDict` instead of a + ``TypeConversionDict``. + + .. versionchanged:: 0.5 + Returns a :class:`TypeConversionDict` instead of a regular dict. + The ``cls`` parameter was added. + """ + if isinstance(header, dict): + header = header.get("HTTP_COOKIE", "") + elif header is None: + header = "" + + # PEP 3333 sends headers through the environ as latin1 decoded + # strings. Encode strings back to bytes for parsing. + if isinstance(header, str): + header = header.encode("latin1", "replace") + + if cls is None: + cls = ds.MultiDict + + def _parse_pairs() -> t.Iterator[t.Tuple[str, str]]: + for key, val in _cookie_parse_impl(header): # type: ignore + key_str = _to_str(key, charset, errors, allow_none_charset=True) + + if not key_str: + continue + + val_str = _to_str(val, charset, errors, allow_none_charset=True) + yield key_str, val_str + + return cls(_parse_pairs()) + + +def dump_cookie( + key: str, + value: t.Union[bytes, str] = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: t.Optional[str] = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + charset: str = "utf-8", + sync_expires: bool = True, + max_size: int = 4093, + samesite: t.Optional[str] = None, +) -> str: + """Create a Set-Cookie header without the ``Set-Cookie`` prefix. + + The return value is usually restricted to ascii as the vast majority + of values are properly escaped, but that is no guarantee. It's + tunneled through latin1 as required by :pep:`3333`. + + The return value is not ASCII safe if the key contains unicode + characters. This is technically against the specification but + happens in the wild. It's strongly recommended to not use + non-ASCII values for the keys. + + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. Additionally `timedelta` objects + are accepted, too. + :param expires: should be a `datetime` object or unix timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: Use this if you want to set a cross-domain cookie. For + example, ``domain=".example.com"`` will set a cookie + that is readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: The cookie will only be available via HTTPS + :param httponly: disallow JavaScript to access the cookie. This is an + extension to the cookie standard and probably not + supported by all browsers. + :param charset: the encoding for string values. + :param sync_expires: automatically set expires if max_age is defined + but expires not. + :param max_size: Warn if the final header value exceeds this size. The + default, 4093, should be safely `supported by most browsers + `_. Set to 0 to disable this check. + :param samesite: Limits the scope of the cookie such that it will + only be attached to requests if those requests are same-site. + + .. _`cookie`: http://browsercookielimits.squawky.net/ + + .. versionchanged:: 1.0.0 + The string ``'None'`` is accepted for ``samesite``. + """ + key = _to_bytes(key, charset) + value = _to_bytes(value, charset) + + if path is not None: + from .urls import iri_to_uri + + path = iri_to_uri(path, charset) + + domain = _make_cookie_domain(domain) + + if isinstance(max_age, timedelta): + max_age = int(max_age.total_seconds()) + + if expires is not None: + if not isinstance(expires, str): + expires = http_date(expires) + elif max_age is not None and sync_expires: + expires = http_date(datetime.now(tz=timezone.utc).timestamp() + max_age) + + if samesite is not None: + samesite = samesite.title() + + if samesite not in {"Strict", "Lax", "None"}: + raise ValueError("SameSite must be 'Strict', 'Lax', or 'None'.") + + buf = [key + b"=" + _cookie_quote(value)] + + # XXX: In theory all of these parameters that are not marked with `None` + # should be quoted. Because stdlib did not quote it before I did not + # want to introduce quoting there now. + for k, v, q in ( + (b"Domain", domain, True), + (b"Expires", expires, False), + (b"Max-Age", max_age, False), + (b"Secure", secure, None), + (b"HttpOnly", httponly, None), + (b"Path", path, False), + (b"SameSite", samesite, False), + ): + if q is None: + if v: + buf.append(k) + continue + + if v is None: + continue + + tmp = bytearray(k) + if not isinstance(v, (bytes, bytearray)): + v = _to_bytes(str(v), charset) + if q: + v = _cookie_quote(v) + tmp += b"=" + v + buf.append(bytes(tmp)) + + # The return value will be an incorrectly encoded latin1 header for + # consistency with the headers object. + rv = b"; ".join(buf) + rv = rv.decode("latin1") + + # Warn if the final value of the cookie is larger than the limit. If the + # cookie is too large, then it may be silently ignored by the browser, + # which can be quite hard to debug. + cookie_size = len(rv) + + if max_size and cookie_size > max_size: + value_size = len(value) + warnings.warn( + f"The {key.decode(charset)!r} cookie is too large: the value was" + f" {value_size} bytes but the" + f" header required {cookie_size - value_size} extra bytes. The final size" + f" was {cookie_size} bytes but the limit is {max_size} bytes. Browsers may" + f" silently ignore cookies larger than this.", + stacklevel=2, + ) + + return rv + + +def is_byte_range_valid( + start: t.Optional[int], stop: t.Optional[int], length: t.Optional[int] +) -> bool: + """Checks if a given byte content range is valid for the given length. + + .. versionadded:: 0.7 + """ + if (start is None) != (stop is None): + return False + elif start is None: + return length is None or length >= 0 + elif length is None: + return 0 <= start < stop # type: ignore + elif start >= stop: # type: ignore + return False + return 0 <= start < length + + +# circular dependencies +from . import datastructures as ds diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/local.py b/axios-example/lib/python3.10/site-packages/werkzeug/local.py new file mode 100644 index 0000000..e297f38 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/local.py @@ -0,0 +1,532 @@ +import copy +import math +import operator +import typing as t +from contextvars import ContextVar +from functools import partial +from functools import update_wrapper + +from .wsgi import ClosingIterator + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def release_local(local: t.Union["Local", "LocalStack"]) -> None: + """Releases the contents of the local for the current context. + This makes it possible to use locals without a manager. + + Example:: + + >>> loc = Local() + >>> loc.foo = 42 + >>> release_local(loc) + >>> hasattr(loc, 'foo') + False + + With this function one can release :class:`Local` objects as well + as :class:`LocalStack` objects. However it is not possible to + release data held by proxies that way, one always has to retain + a reference to the underlying local object in order to be able + to release it. + + .. versionadded:: 0.6.1 + """ + local.__release_local__() + + +class Local: + __slots__ = ("_storage",) + + def __init__(self) -> None: + object.__setattr__(self, "_storage", ContextVar("local_storage")) + + def __iter__(self) -> t.Iterator[t.Tuple[int, t.Any]]: + return iter(self._storage.get({}).items()) + + def __call__(self, proxy: str) -> "LocalProxy": + """Create a proxy for a name.""" + return LocalProxy(self, proxy) + + def __release_local__(self) -> None: + self._storage.set({}) + + def __getattr__(self, name: str) -> t.Any: + values = self._storage.get({}) + try: + return values[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + values = self._storage.get({}).copy() + values[name] = value + self._storage.set(values) + + def __delattr__(self, name: str) -> None: + values = self._storage.get({}).copy() + try: + del values[name] + self._storage.set(values) + except KeyError: + raise AttributeError(name) from None + + +class LocalStack: + """This class works similar to a :class:`Local` but keeps a stack + of objects instead. This is best explained with an example:: + + >>> ls = LocalStack() + >>> ls.push(42) + >>> ls.top + 42 + >>> ls.push(23) + >>> ls.top + 23 + >>> ls.pop() + 23 + >>> ls.top + 42 + + They can be force released by using a :class:`LocalManager` or with + the :func:`release_local` function but the correct way is to pop the + item from the stack after using. When the stack is empty it will + no longer be bound to the current context (and as such released). + + By calling the stack without arguments it returns a proxy that resolves to + the topmost item on the stack. + + .. versionadded:: 0.6.1 + """ + + def __init__(self) -> None: + self._local = Local() + + def __release_local__(self) -> None: + self._local.__release_local__() + + def __call__(self) -> "LocalProxy": + def _lookup() -> t.Any: + rv = self.top + if rv is None: + raise RuntimeError("object unbound") + return rv + + return LocalProxy(_lookup) + + def push(self, obj: t.Any) -> t.List[t.Any]: + """Pushes a new item to the stack""" + rv = getattr(self._local, "stack", []).copy() + rv.append(obj) + self._local.stack = rv + return rv + + def pop(self) -> t.Any: + """Removes the topmost item from the stack, will return the + old value or `None` if the stack was already empty. + """ + stack = getattr(self._local, "stack", None) + if stack is None: + return None + elif len(stack) == 1: + release_local(self._local) + return stack[-1] + else: + return stack.pop() + + @property + def top(self) -> t.Any: + """The topmost item on the stack. If the stack is empty, + `None` is returned. + """ + try: + return self._local.stack[-1] + except (AttributeError, IndexError): + return None + + +class LocalManager: + """Local objects cannot manage themselves. For that you need a local + manager. You can pass a local manager multiple locals or add them + later by appending them to `manager.locals`. Every time the manager + cleans up, it will clean up all the data left in the locals for this + context. + + .. versionchanged:: 2.0 + ``ident_func`` is deprecated and will be removed in Werkzeug + 2.1. + + .. versionchanged:: 0.6.1 + The :func:`release_local` function can be used instead of a + manager. + + .. versionchanged:: 0.7 + The ``ident_func`` parameter was added. + """ + + def __init__( + self, locals: t.Optional[t.Iterable[t.Union[Local, LocalStack]]] = None + ) -> None: + if locals is None: + self.locals = [] + elif isinstance(locals, Local): + self.locals = [locals] + else: + self.locals = list(locals) + + def cleanup(self) -> None: + """Manually clean up the data in the locals for this context. Call + this at the end of the request or use `make_middleware()`. + """ + for local in self.locals: + release_local(local) + + def make_middleware(self, app: "WSGIApplication") -> "WSGIApplication": + """Wrap a WSGI application so that cleaning up happens after + request end. + """ + + def application( + environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + return ClosingIterator(app(environ, start_response), self.cleanup) + + return application + + def middleware(self, func: "WSGIApplication") -> "WSGIApplication": + """Like `make_middleware` but for decorating functions. + + Example usage:: + + @manager.middleware + def application(environ, start_response): + ... + + The difference to `make_middleware` is that the function passed + will have all the arguments copied from the inner application + (name, docstring, module). + """ + return update_wrapper(self.make_middleware(func), func) + + def __repr__(self) -> str: + return f"<{type(self).__name__} storages: {len(self.locals)}>" + + +class _ProxyLookup: + """Descriptor that handles proxied attribute lookup for + :class:`LocalProxy`. + + :param f: The built-in function this attribute is accessed through. + Instead of looking up the special method, the function call + is redone on the object. + :param fallback: Return this function if the proxy is unbound + instead of raising a :exc:`RuntimeError`. + :param is_attr: This proxied name is an attribute, not a function. + Call the fallback immediately to get the value. + :param class_value: Value to return when accessed from the + ``LocalProxy`` class directly. Used for ``__doc__`` so building + docs still works. + """ + + __slots__ = ("bind_f", "fallback", "is_attr", "class_value", "name") + + def __init__( + self, + f: t.Optional[t.Callable] = None, + fallback: t.Optional[t.Callable] = None, + class_value: t.Optional[t.Any] = None, + is_attr: bool = False, + ) -> None: + bind_f: t.Optional[t.Callable[["LocalProxy", t.Any], t.Callable]] + + if hasattr(f, "__get__"): + # A Python function, can be turned into a bound method. + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + return f.__get__(obj, type(obj)) # type: ignore + + elif f is not None: + # A C function, use partial to bind the first argument. + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + return partial(f, obj) # type: ignore + + else: + # Use getattr, which will produce a bound method. + bind_f = None + + self.bind_f = bind_f + self.fallback = fallback + self.class_value = class_value + self.is_attr = is_attr + + def __set_name__(self, owner: "LocalProxy", name: str) -> None: + self.name = name + + def __get__(self, instance: "LocalProxy", owner: t.Optional[type] = None) -> t.Any: + if instance is None: + if self.class_value is not None: + return self.class_value + + return self + + try: + obj = instance._get_current_object() + except RuntimeError: + if self.fallback is None: + raise + + fallback = self.fallback.__get__(instance, owner) + + if self.is_attr: + # __class__ and __doc__ are attributes, not methods. + # Call the fallback to get the value. + return fallback() + + return fallback + + if self.bind_f is not None: + return self.bind_f(instance, obj) + + return getattr(obj, self.name) + + def __repr__(self) -> str: + return f"proxy {self.name}" + + def __call__(self, instance: "LocalProxy", *args: t.Any, **kwargs: t.Any) -> t.Any: + """Support calling unbound methods from the class. For example, + this happens with ``copy.copy``, which does + ``type(x).__copy__(x)``. ``type(x)`` can't be proxied, so it + returns the proxy type and descriptor. + """ + return self.__get__(instance, type(instance))(*args, **kwargs) + + +class _ProxyIOp(_ProxyLookup): + """Look up an augmented assignment method on a proxied object. The + method is wrapped to return the proxy instead of the object. + """ + + __slots__ = () + + def __init__( + self, f: t.Optional[t.Callable] = None, fallback: t.Optional[t.Callable] = None + ) -> None: + super().__init__(f, fallback) + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + def i_op(self: t.Any, other: t.Any) -> "LocalProxy": + f(self, other) # type: ignore + return instance + + return i_op.__get__(obj, type(obj)) # type: ignore + + self.bind_f = bind_f + + +def _l_to_r_op(op: F) -> F: + """Swap the argument order to turn an l-op into an r-op.""" + + def r_op(obj: t.Any, other: t.Any) -> t.Any: + return op(other, obj) + + return t.cast(F, r_op) + + +class LocalProxy: + """A proxy to the object bound to a :class:`Local`. All operations + on the proxy are forwarded to the bound object. If no object is + bound, a :exc:`RuntimeError` is raised. + + .. code-block:: python + + from werkzeug.local import Local + l = Local() + + # a proxy to whatever l.user is set to + user = l("user") + + from werkzeug.local import LocalStack + _request_stack = LocalStack() + + # a proxy to _request_stack.top + request = _request_stack() + + # a proxy to the session attribute of the request proxy + session = LocalProxy(lambda: request.session) + + ``__repr__`` and ``__class__`` are forwarded, so ``repr(x)`` and + ``isinstance(x, cls)`` will look like the proxied object. Use + ``issubclass(type(x), LocalProxy)`` to check if an object is a + proxy. + + .. code-block:: python + + repr(user) # + isinstance(user, User) # True + issubclass(type(user), LocalProxy) # True + + :param local: The :class:`Local` or callable that provides the + proxied object. + :param name: The attribute name to look up on a :class:`Local`. Not + used if a callable is given. + + .. versionchanged:: 2.0 + Updated proxied attributes and methods to reflect the current + data model. + + .. versionchanged:: 0.6.1 + The class can be instantiated with a callable. + """ + + __slots__ = ("__local", "__name", "__wrapped__") + + def __init__( + self, + local: t.Union["Local", t.Callable[[], t.Any]], + name: t.Optional[str] = None, + ) -> None: + object.__setattr__(self, "_LocalProxy__local", local) + object.__setattr__(self, "_LocalProxy__name", name) + + if callable(local) and not hasattr(local, "__release_local__"): + # "local" is a callable that is not an instance of Local or + # LocalManager: mark it as a wrapped function. + object.__setattr__(self, "__wrapped__", local) + + def _get_current_object(self) -> t.Any: + """Return the current object. This is useful if you want the real + object behind the proxy at a time for performance reasons or because + you want to pass the object into a different context. + """ + if not hasattr(self.__local, "__release_local__"): # type: ignore + return self.__local() # type: ignore + + try: + return getattr(self.__local, self.__name) # type: ignore + except AttributeError: + name = self.__name # type: ignore + raise RuntimeError(f"no object bound to {name}") from None + + __doc__ = _ProxyLookup( # type: ignore + class_value=__doc__, fallback=lambda self: type(self).__doc__, is_attr=True + ) + # __del__ should only delete the proxy + __repr__ = _ProxyLookup( # type: ignore + repr, fallback=lambda self: f"<{type(self).__name__} unbound>" + ) + __str__ = _ProxyLookup(str) # type: ignore + __bytes__ = _ProxyLookup(bytes) + __format__ = _ProxyLookup() # type: ignore + __lt__ = _ProxyLookup(operator.lt) + __le__ = _ProxyLookup(operator.le) + __eq__ = _ProxyLookup(operator.eq) # type: ignore + __ne__ = _ProxyLookup(operator.ne) # type: ignore + __gt__ = _ProxyLookup(operator.gt) + __ge__ = _ProxyLookup(operator.ge) + __hash__ = _ProxyLookup(hash) # type: ignore + __bool__ = _ProxyLookup(bool, fallback=lambda self: False) + __getattr__ = _ProxyLookup(getattr) + # __getattribute__ triggered through __getattr__ + __setattr__ = _ProxyLookup(setattr) # type: ignore + __delattr__ = _ProxyLookup(delattr) # type: ignore + __dir__ = _ProxyLookup(dir, fallback=lambda self: []) # type: ignore + # __get__ (proxying descriptor not supported) + # __set__ (descriptor) + # __delete__ (descriptor) + # __set_name__ (descriptor) + # __objclass__ (descriptor) + # __slots__ used by proxy itself + # __dict__ (__getattr__) + # __weakref__ (__getattr__) + # __init_subclass__ (proxying metaclass not supported) + # __prepare__ (metaclass) + __class__ = _ProxyLookup( + fallback=lambda self: type(self), is_attr=True + ) # type: ignore + __instancecheck__ = _ProxyLookup(lambda self, other: isinstance(other, self)) + __subclasscheck__ = _ProxyLookup(lambda self, other: issubclass(other, self)) + # __class_getitem__ triggered through __getitem__ + __call__ = _ProxyLookup(lambda self, *args, **kwargs: self(*args, **kwargs)) + __len__ = _ProxyLookup(len) + __length_hint__ = _ProxyLookup(operator.length_hint) + __getitem__ = _ProxyLookup(operator.getitem) + __setitem__ = _ProxyLookup(operator.setitem) + __delitem__ = _ProxyLookup(operator.delitem) + # __missing__ triggered through __getitem__ + __iter__ = _ProxyLookup(iter) + __next__ = _ProxyLookup(next) + __reversed__ = _ProxyLookup(reversed) + __contains__ = _ProxyLookup(operator.contains) + __add__ = _ProxyLookup(operator.add) + __sub__ = _ProxyLookup(operator.sub) + __mul__ = _ProxyLookup(operator.mul) + __matmul__ = _ProxyLookup(operator.matmul) + __truediv__ = _ProxyLookup(operator.truediv) + __floordiv__ = _ProxyLookup(operator.floordiv) + __mod__ = _ProxyLookup(operator.mod) + __divmod__ = _ProxyLookup(divmod) + __pow__ = _ProxyLookup(pow) + __lshift__ = _ProxyLookup(operator.lshift) + __rshift__ = _ProxyLookup(operator.rshift) + __and__ = _ProxyLookup(operator.and_) + __xor__ = _ProxyLookup(operator.xor) + __or__ = _ProxyLookup(operator.or_) + __radd__ = _ProxyLookup(_l_to_r_op(operator.add)) + __rsub__ = _ProxyLookup(_l_to_r_op(operator.sub)) + __rmul__ = _ProxyLookup(_l_to_r_op(operator.mul)) + __rmatmul__ = _ProxyLookup(_l_to_r_op(operator.matmul)) + __rtruediv__ = _ProxyLookup(_l_to_r_op(operator.truediv)) + __rfloordiv__ = _ProxyLookup(_l_to_r_op(operator.floordiv)) + __rmod__ = _ProxyLookup(_l_to_r_op(operator.mod)) + __rdivmod__ = _ProxyLookup(_l_to_r_op(divmod)) + __rpow__ = _ProxyLookup(_l_to_r_op(pow)) + __rlshift__ = _ProxyLookup(_l_to_r_op(operator.lshift)) + __rrshift__ = _ProxyLookup(_l_to_r_op(operator.rshift)) + __rand__ = _ProxyLookup(_l_to_r_op(operator.and_)) + __rxor__ = _ProxyLookup(_l_to_r_op(operator.xor)) + __ror__ = _ProxyLookup(_l_to_r_op(operator.or_)) + __iadd__ = _ProxyIOp(operator.iadd) + __isub__ = _ProxyIOp(operator.isub) + __imul__ = _ProxyIOp(operator.imul) + __imatmul__ = _ProxyIOp(operator.imatmul) + __itruediv__ = _ProxyIOp(operator.itruediv) + __ifloordiv__ = _ProxyIOp(operator.ifloordiv) + __imod__ = _ProxyIOp(operator.imod) + __ipow__ = _ProxyIOp(operator.ipow) + __ilshift__ = _ProxyIOp(operator.ilshift) + __irshift__ = _ProxyIOp(operator.irshift) + __iand__ = _ProxyIOp(operator.iand) + __ixor__ = _ProxyIOp(operator.ixor) + __ior__ = _ProxyIOp(operator.ior) + __neg__ = _ProxyLookup(operator.neg) + __pos__ = _ProxyLookup(operator.pos) + __abs__ = _ProxyLookup(abs) + __invert__ = _ProxyLookup(operator.invert) + __complex__ = _ProxyLookup(complex) + __int__ = _ProxyLookup(int) + __float__ = _ProxyLookup(float) + __index__ = _ProxyLookup(operator.index) + __round__ = _ProxyLookup(round) + __trunc__ = _ProxyLookup(math.trunc) + __floor__ = _ProxyLookup(math.floor) + __ceil__ = _ProxyLookup(math.ceil) + __enter__ = _ProxyLookup() + __exit__ = _ProxyLookup() + __await__ = _ProxyLookup() + __aiter__ = _ProxyLookup() + __anext__ = _ProxyLookup() + __aenter__ = _ProxyLookup() + __aexit__ = _ProxyLookup() + __copy__ = _ProxyLookup(copy.copy) + __deepcopy__ = _ProxyLookup(copy.deepcopy) + # __getnewargs_ex__ (pickle through proxy not supported) + # __getnewargs__ (pickle) + # __getstate__ (pickle) + # __setstate__ (pickle) + # __reduce__ (pickle) + # __reduce_ex__ (pickle) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/__init__.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/__init__.py new file mode 100644 index 0000000..6ddcf7f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/__init__.py @@ -0,0 +1,22 @@ +""" +Middleware +========== + +A WSGI middleware is a WSGI application that wraps another application +in order to observe or change its behavior. Werkzeug provides some +middleware for common use cases. + +.. toctree:: + :maxdepth: 1 + + proxy_fix + shared_data + dispatcher + http_proxy + lint + profiler + +The :doc:`interactive debugger ` is also a middleware that can +be applied manually, although it is typically used automatically with +the :doc:`development server `. +""" diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py new file mode 100644 index 0000000..ace1c75 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py @@ -0,0 +1,78 @@ +""" +Application Dispatcher +====================== + +This middleware creates a single WSGI application that dispatches to +multiple other WSGI applications mounted at different URL paths. + +A common example is writing a Single Page Application, where you have a +backend API and a frontend written in JavaScript that does the routing +in the browser rather than requesting different pages from the server. +The frontend is a single HTML and JS file that should be served for any +path besides "/api". + +This example dispatches to an API app under "/api", an admin app +under "/admin", and an app that serves frontend files for all other +requests:: + + app = DispatcherMiddleware(serve_frontend, { + '/api': api_app, + '/admin': admin_app, + }) + +In production, you might instead handle this at the HTTP server level, +serving files or proxying to application servers based on location. The +API and admin apps would each be deployed with a separate WSGI server, +and the static files would be served directly by the HTTP server. + +.. autoclass:: DispatcherMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class DispatcherMiddleware: + """Combine multiple applications as a single WSGI application. + Requests are dispatched to an application based on the path it is + mounted under. + + :param app: The WSGI application to dispatch to if the request + doesn't match a mounted path. + :param mounts: Maps path prefixes to applications for dispatching. + """ + + def __init__( + self, + app: "WSGIApplication", + mounts: t.Optional[t.Dict[str, "WSGIApplication"]] = None, + ) -> None: + self.app = app + self.mounts = mounts or {} + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + script = environ.get("PATH_INFO", "") + path_info = "" + + while "/" in script: + if script in self.mounts: + app = self.mounts[script] + break + + script, last_item = script.rsplit("/", 1) + path_info = f"/{last_item}{path_info}" + else: + app = self.mounts.get(script, self.app) + + original_script_name = environ.get("SCRIPT_NAME", "") + environ["SCRIPT_NAME"] = original_script_name + script + environ["PATH_INFO"] = path_info + return app(environ, start_response) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py new file mode 100644 index 0000000..1cde458 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py @@ -0,0 +1,230 @@ +""" +Basic HTTP Proxy +================ + +.. autoclass:: ProxyMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t +from http import client + +from ..datastructures import EnvironHeaders +from ..http import is_hop_by_hop_header +from ..urls import url_parse +from ..urls import url_quote +from ..wsgi import get_input_stream + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyMiddleware: + """Proxy requests under a path to an external server, routing other + requests to the app. + + This middleware can only proxy HTTP requests, as HTTP is the only + protocol handled by the WSGI server. Other protocols, such as + WebSocket requests, cannot be proxied at this layer. This should + only be used for development, in production a real proxy server + should be used. + + The middleware takes a dict mapping a path prefix to a dict + describing the host to be proxied to:: + + app = ProxyMiddleware(app, { + "/static/": { + "target": "http://127.0.0.1:5001/", + } + }) + + Each host has the following options: + + ``target``: + The target URL to dispatch to. This is required. + ``remove_prefix``: + Whether to remove the prefix from the URL before dispatching it + to the target. The default is ``False``. + ``host``: + ``""`` (default): + The host header is automatically rewritten to the URL of the + target. + ``None``: + The host header is unmodified from the client request. + Any other value: + The host header is overwritten with the value. + ``headers``: + A dictionary of headers to be sent with the request to the + target. The default is ``{}``. + ``ssl_context``: + A :class:`ssl.SSLContext` defining how to verify requests if the + target is HTTPS. The default is ``None``. + + In the example above, everything under ``"/static/"`` is proxied to + the server on port 5001. The host header is rewritten to the target, + and the ``"/static/"`` prefix is removed from the URLs. + + :param app: The WSGI application to wrap. + :param targets: Proxy target configurations. See description above. + :param chunk_size: Size of chunks to read from input stream and + write to target. + :param timeout: Seconds before an operation to a target fails. + + .. versionadded:: 0.14 + """ + + def __init__( + self, + app: "WSGIApplication", + targets: t.Mapping[str, t.Dict[str, t.Any]], + chunk_size: int = 2 << 13, + timeout: int = 10, + ) -> None: + def _set_defaults(opts: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + opts.setdefault("remove_prefix", False) + opts.setdefault("host", "") + opts.setdefault("headers", {}) + opts.setdefault("ssl_context", None) + return opts + + self.app = app + self.targets = { + f"/{k.strip('/')}/": _set_defaults(v) for k, v in targets.items() + } + self.chunk_size = chunk_size + self.timeout = timeout + + def proxy_to( + self, opts: t.Dict[str, t.Any], path: str, prefix: str + ) -> "WSGIApplication": + target = url_parse(opts["target"]) + host = t.cast(str, target.ascii_host) + + def application( + environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + headers = list(EnvironHeaders(environ).items()) + headers[:] = [ + (k, v) + for k, v in headers + if not is_hop_by_hop_header(k) + and k.lower() not in ("content-length", "host") + ] + headers.append(("Connection", "close")) + + if opts["host"] == "": + headers.append(("Host", host)) + elif opts["host"] is None: + headers.append(("Host", environ["HTTP_HOST"])) + else: + headers.append(("Host", opts["host"])) + + headers.extend(opts["headers"].items()) + remote_path = path + + if opts["remove_prefix"]: + remote_path = remote_path[len(prefix) :].lstrip("/") + remote_path = f"{target.path.rstrip('/')}/{remote_path}" + + content_length = environ.get("CONTENT_LENGTH") + chunked = False + + if content_length not in ("", None): + headers.append(("Content-Length", content_length)) # type: ignore + elif content_length is not None: + headers.append(("Transfer-Encoding", "chunked")) + chunked = True + + try: + if target.scheme == "http": + con = client.HTTPConnection( + host, target.port or 80, timeout=self.timeout + ) + elif target.scheme == "https": + con = client.HTTPSConnection( + host, + target.port or 443, + timeout=self.timeout, + context=opts["ssl_context"], + ) + else: + raise RuntimeError( + "Target scheme must be 'http' or 'https', got" + f" {target.scheme!r}." + ) + + con.connect() + remote_url = url_quote(remote_path) + querystring = environ["QUERY_STRING"] + + if querystring: + remote_url = f"{remote_url}?{querystring}" + + con.putrequest(environ["REQUEST_METHOD"], remote_url, skip_host=True) + + for k, v in headers: + if k.lower() == "connection": + v = "close" + + con.putheader(k, v) + + con.endheaders() + stream = get_input_stream(environ) + + while True: + data = stream.read(self.chunk_size) + + if not data: + break + + if chunked: + con.send(b"%x\r\n%s\r\n" % (len(data), data)) + else: + con.send(data) + + resp = con.getresponse() + except OSError: + from ..exceptions import BadGateway + + return BadGateway()(environ, start_response) + + start_response( + f"{resp.status} {resp.reason}", + [ + (k.title(), v) + for k, v in resp.getheaders() + if not is_hop_by_hop_header(k) + ], + ) + + def read() -> t.Iterator[bytes]: + while True: + try: + data = resp.read(self.chunk_size) + except OSError: + break + + if not data: + break + + yield data + + return read() + + return application + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + path = environ["PATH_INFO"] + app = self.app + + for prefix, opts in self.targets.items(): + if path.startswith(prefix): + app = self.proxy_to(opts, path, prefix) + break + + return app(environ, start_response) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/lint.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/lint.py new file mode 100644 index 0000000..3a74718 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/lint.py @@ -0,0 +1,420 @@ +""" +WSGI Protocol Linter +==================== + +This module provides a middleware that performs sanity checks on the +behavior of the WSGI server and application. It checks that the +:pep:`3333` WSGI spec is properly implemented. It also warns on some +common HTTP errors such as non-empty responses for 304 status codes. + +.. autoclass:: LintMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t +from types import TracebackType +from urllib.parse import urlparse +from warnings import warn + +from ..datastructures import Headers +from ..http import is_entity_header +from ..wsgi import FileWrapper + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class WSGIWarning(Warning): + """Warning class for WSGI warnings.""" + + +class HTTPWarning(Warning): + """Warning class for HTTP warnings.""" + + +def check_type(context: str, obj: object, need: t.Type = str) -> None: + if type(obj) is not need: + warn( + f"{context!r} requires {need.__name__!r}, got {type(obj).__name__!r}.", + WSGIWarning, + stacklevel=3, + ) + + +class InputStream: + def __init__(self, stream: t.IO[bytes]) -> None: + self._stream = stream + + def read(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "WSGI does not guarantee an EOF marker on the input stream, thus making" + " calls to 'wsgi.input.read()' unsafe. Conforming servers may never" + " return from this call.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) != 1: + warn( + "Too many parameters passed to 'wsgi.input.read()'.", + WSGIWarning, + stacklevel=2, + ) + return self._stream.read(*args) + + def readline(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "Calls to 'wsgi.input.readline()' without arguments are unsafe. Use" + " 'wsgi.input.read()' instead.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) == 1: + warn( + "'wsgi.input.readline()' was called with a size hint. WSGI does not" + " support this, although it's available on all major servers.", + WSGIWarning, + stacklevel=2, + ) + else: + raise TypeError("Too many arguments passed to 'wsgi.input.readline()'.") + return self._stream.readline(*args) + + def __iter__(self) -> t.Iterator[bytes]: + try: + return iter(self._stream) + except TypeError: + warn("'wsgi.input' is not iterable.", WSGIWarning, stacklevel=2) + return iter(()) + + def close(self) -> None: + warn("The application closed the input stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class ErrorStream: + def __init__(self, stream: t.IO[str]) -> None: + self._stream = stream + + def write(self, s: str) -> None: + check_type("wsgi.error.write()", s, str) + self._stream.write(s) + + def flush(self) -> None: + self._stream.flush() + + def writelines(self, seq: t.Iterable[str]) -> None: + for line in seq: + self.write(line) + + def close(self) -> None: + warn("The application closed the error stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class GuardedWrite: + def __init__(self, write: t.Callable[[bytes], object], chunks: t.List[int]) -> None: + self._write = write + self._chunks = chunks + + def __call__(self, s: bytes) -> None: + check_type("write()", s, bytes) + self._write(s) + self._chunks.append(len(s)) + + +class GuardedIterator: + def __init__( + self, + iterator: t.Iterable[bytes], + headers_set: t.Tuple[int, Headers], + chunks: t.List[int], + ) -> None: + self._iterator = iterator + self._next = iter(iterator).__next__ + self.closed = False + self.headers_set = headers_set + self.chunks = chunks + + def __iter__(self) -> "GuardedIterator": + return self + + def __next__(self) -> bytes: + if self.closed: + warn("Iterated over closed 'app_iter'.", WSGIWarning, stacklevel=2) + + rv = self._next() + + if not self.headers_set: + warn( + "The application returned before it started the response.", + WSGIWarning, + stacklevel=2, + ) + + check_type("application iterator items", rv, bytes) + self.chunks.append(len(rv)) + return rv + + def close(self) -> None: + self.closed = True + + if hasattr(self._iterator, "close"): + self._iterator.close() # type: ignore + + if self.headers_set: + status_code, headers = self.headers_set + bytes_sent = sum(self.chunks) + content_length = headers.get("content-length", type=int) + + if status_code == 304: + for key, _value in headers: + key = key.lower() + if key not in ("expires", "content-location") and is_entity_header( + key + ): + warn( + f"Entity header {key!r} found in 304 response.", HTTPWarning + ) + if bytes_sent: + warn("304 responses must not have a body.", HTTPWarning) + elif 100 <= status_code < 200 or status_code == 204: + if content_length != 0: + warn( + f"{status_code} responses must have an empty content length.", + HTTPWarning, + ) + if bytes_sent: + warn(f"{status_code} responses must not have a body.", HTTPWarning) + elif content_length is not None and content_length != bytes_sent: + warn( + "Content-Length and the number of bytes sent to the" + " client do not match.", + WSGIWarning, + ) + + def __del__(self) -> None: + if not self.closed: + try: + warn( + "Iterator was garbage collected before it was closed.", WSGIWarning + ) + except Exception: + pass + + +class LintMiddleware: + """Warns about common errors in the WSGI and HTTP behavior of the + server and wrapped application. Some of the issues it checks are: + + - invalid status codes + - non-bytes sent to the WSGI server + - strings returned from the WSGI application + - non-empty conditional responses + - unquoted etags + - relative URLs in the Location header + - unsafe calls to wsgi.input + - unclosed iterators + + Error information is emitted using the :mod:`warnings` module. + + :param app: The WSGI application to wrap. + + .. code-block:: python + + from werkzeug.middleware.lint import LintMiddleware + app = LintMiddleware(app) + """ + + def __init__(self, app: "WSGIApplication") -> None: + self.app = app + + def check_environ(self, environ: "WSGIEnvironment") -> None: + if type(environ) is not dict: + warn( + "WSGI environment is not a standard Python dict.", + WSGIWarning, + stacklevel=4, + ) + for key in ( + "REQUEST_METHOD", + "SERVER_NAME", + "SERVER_PORT", + "wsgi.version", + "wsgi.input", + "wsgi.errors", + "wsgi.multithread", + "wsgi.multiprocess", + "wsgi.run_once", + ): + if key not in environ: + warn( + f"Required environment key {key!r} not found", + WSGIWarning, + stacklevel=3, + ) + if environ["wsgi.version"] != (1, 0): + warn("Environ is not a WSGI 1.0 environ.", WSGIWarning, stacklevel=3) + + script_name = environ.get("SCRIPT_NAME", "") + path_info = environ.get("PATH_INFO", "") + + if script_name and script_name[0] != "/": + warn( + f"'SCRIPT_NAME' does not start with a slash: {script_name!r}", + WSGIWarning, + stacklevel=3, + ) + + if path_info and path_info[0] != "/": + warn( + f"'PATH_INFO' does not start with a slash: {path_info!r}", + WSGIWarning, + stacklevel=3, + ) + + def check_start_response( + self, + status: str, + headers: t.List[t.Tuple[str, str]], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ], + ) -> t.Tuple[int, Headers]: + check_type("status", status, str) + status_code_str = status.split(None, 1)[0] + + if len(status_code_str) != 3 or not status_code_str.isdigit(): + warn("Status code must be three digits.", WSGIWarning, stacklevel=3) + + if len(status) < 4 or status[3] != " ": + warn( + f"Invalid value for status {status!r}. Valid status strings are three" + " digits, a space and a status explanation.", + WSGIWarning, + stacklevel=3, + ) + + status_code = int(status_code_str) + + if status_code < 100: + warn("Status code < 100 detected.", WSGIWarning, stacklevel=3) + + if type(headers) is not list: + warn("Header list is not a list.", WSGIWarning, stacklevel=3) + + for item in headers: + if type(item) is not tuple or len(item) != 2: + warn("Header items must be 2-item tuples.", WSGIWarning, stacklevel=3) + name, value = item + if type(name) is not str or type(value) is not str: + warn( + "Header keys and values must be strings.", WSGIWarning, stacklevel=3 + ) + if name.lower() == "status": + warn( + "The status header is not supported due to" + " conflicts with the CGI spec.", + WSGIWarning, + stacklevel=3, + ) + + if exc_info is not None and not isinstance(exc_info, tuple): + warn("Invalid value for exc_info.", WSGIWarning, stacklevel=3) + + headers = Headers(headers) + self.check_headers(headers) + + return status_code, headers + + def check_headers(self, headers: Headers) -> None: + etag = headers.get("etag") + + if etag is not None: + if etag.startswith(("W/", "w/")): + if etag.startswith("w/"): + warn( + "Weak etag indicator should be upper case.", + HTTPWarning, + stacklevel=4, + ) + + etag = etag[2:] + + if not (etag[:1] == etag[-1:] == '"'): + warn("Unquoted etag emitted.", HTTPWarning, stacklevel=4) + + location = headers.get("location") + + if location is not None: + if not urlparse(location).netloc: + warn( + "Absolute URLs required for location header.", + HTTPWarning, + stacklevel=4, + ) + + def check_iterator(self, app_iter: t.Iterable[bytes]) -> None: + if isinstance(app_iter, bytes): + warn( + "The application returned a bytestring. The response will send one" + " character at a time to the client, which will kill performance." + " Return a list or iterable instead.", + WSGIWarning, + stacklevel=3, + ) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Iterable[bytes]: + if len(args) != 2: + warn("A WSGI app takes two arguments.", WSGIWarning, stacklevel=2) + + if kwargs: + warn( + "A WSGI app does not take keyword arguments.", WSGIWarning, stacklevel=2 + ) + + environ: "WSGIEnvironment" = args[0] + start_response: "StartResponse" = args[1] + + self.check_environ(environ) + environ["wsgi.input"] = InputStream(environ["wsgi.input"]) + environ["wsgi.errors"] = ErrorStream(environ["wsgi.errors"]) + + # Hook our own file wrapper in so that applications will always + # iterate to the end and we can check the content length. + environ["wsgi.file_wrapper"] = FileWrapper + + headers_set: t.List[t.Any] = [] + chunks: t.List[int] = [] + + def checking_start_response( + *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[bytes], None]: + if len(args) not in {2, 3}: + warn( + f"Invalid number of arguments: {len(args)}, expected 2 or 3.", + WSGIWarning, + stacklevel=2, + ) + + if kwargs: + warn("'start_response' does not take keyword arguments.", WSGIWarning) + + status: str = args[0] + headers: t.List[t.Tuple[str, str]] = args[1] + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = (args[2] if len(args) == 3 else None) + + headers_set[:] = self.check_start_response(status, headers, exc_info) + return GuardedWrite(start_response(status, headers, exc_info), chunks) + + app_iter = self.app(environ, t.cast("StartResponse", checking_start_response)) + self.check_iterator(app_iter) + return GuardedIterator( + app_iter, t.cast(t.Tuple[int, Headers], headers_set), chunks + ) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/profiler.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/profiler.py new file mode 100644 index 0000000..200dae0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/profiler.py @@ -0,0 +1,139 @@ +""" +Application Profiler +==================== + +This module provides a middleware that profiles each request with the +:mod:`cProfile` module. This can help identify bottlenecks in your code +that may be slowing down your application. + +.. autoclass:: ProfilerMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import os.path +import sys +import time +import typing as t +from pstats import Stats + +try: + from cProfile import Profile +except ImportError: + from profile import Profile # type: ignore + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProfilerMiddleware: + """Wrap a WSGI application and profile the execution of each + request. Responses are buffered so that timings are more exact. + + If ``stream`` is given, :class:`pstats.Stats` are written to it + after each request. If ``profile_dir`` is given, :mod:`cProfile` + data files are saved to that directory, one file per request. + + The filename can be customized by passing ``filename_format``. If + it is a string, it will be formatted using :meth:`str.format` with + the following fields available: + + - ``{method}`` - The request method; GET, POST, etc. + - ``{path}`` - The request path or 'root' should one not exist. + - ``{elapsed}`` - The elapsed time of the request. + - ``{time}`` - The time of the request. + + If it is a callable, it will be called with the WSGI ``environ`` + dict and should return a filename. + + :param app: The WSGI application to wrap. + :param stream: Write stats to this stream. Disable with ``None``. + :param sort_by: A tuple of columns to sort stats by. See + :meth:`pstats.Stats.sort_stats`. + :param restrictions: A tuple of restrictions to filter stats by. See + :meth:`pstats.Stats.print_stats`. + :param profile_dir: Save profile data files to this directory. + :param filename_format: Format string for profile data file names, + or a callable returning a name. See explanation above. + + .. code-block:: python + + from werkzeug.middleware.profiler import ProfilerMiddleware + app = ProfilerMiddleware(app) + + .. versionchanged:: 0.15 + Stats are written even if ``profile_dir`` is given, and can be + disable by passing ``stream=None``. + + .. versionadded:: 0.15 + Added ``filename_format``. + + .. versionadded:: 0.9 + Added ``restrictions`` and ``profile_dir``. + """ + + def __init__( + self, + app: "WSGIApplication", + stream: t.IO[str] = sys.stdout, + sort_by: t.Iterable[str] = ("time", "calls"), + restrictions: t.Iterable[t.Union[str, int, float]] = (), + profile_dir: t.Optional[str] = None, + filename_format: str = "{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof", + ) -> None: + self._app = app + self._stream = stream + self._sort_by = sort_by + self._restrictions = restrictions + self._profile_dir = profile_dir + self._filename_format = filename_format + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + response_body: t.List[bytes] = [] + + def catching_start_response(status, headers, exc_info=None): # type: ignore + start_response(status, headers, exc_info) + return response_body.append + + def runapp() -> None: + app_iter = self._app( + environ, t.cast("StartResponse", catching_start_response) + ) + response_body.extend(app_iter) + + if hasattr(app_iter, "close"): + app_iter.close() # type: ignore + + profile = Profile() + start = time.time() + profile.runcall(runapp) + body = b"".join(response_body) + elapsed = time.time() - start + + if self._profile_dir is not None: + if callable(self._filename_format): + filename = self._filename_format(environ) + else: + filename = self._filename_format.format( + method=environ["REQUEST_METHOD"], + path=environ["PATH_INFO"].strip("/").replace("/", ".") or "root", + elapsed=elapsed * 1000.0, + time=time.time(), + ) + filename = os.path.join(self._profile_dir, filename) + profile.dump_stats(filename) + + if self._stream is not None: + stats = Stats(profile, stream=self._stream) + stats.sort_stats(*self._sort_by) + print("-" * 80, file=self._stream) + path_info = environ.get("PATH_INFO", "") + print(f"PATH: {path_info!r}", file=self._stream) + stats.print_stats(*self._restrictions) + print(f"{'-' * 80}\n", file=self._stream) + + return [body] diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py new file mode 100644 index 0000000..4cef7cc --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py @@ -0,0 +1,187 @@ +""" +X-Forwarded-For Proxy Fix +========================= + +This module provides a middleware that adjusts the WSGI environ based on +``X-Forwarded-`` headers that proxies in front of an application may +set. + +When an application is running behind a proxy server, WSGI may see the +request as coming from that server rather than the real client. Proxies +set various headers to track where the request actually came from. + +This middleware should only be used if the application is actually +behind such a proxy, and should be configured with the number of proxies +that are chained in front of it. Not all proxies set all the headers. +Since incoming headers can be faked, you must set how many proxies are +setting each header so the middleware knows what to trust. + +.. autoclass:: ProxyFix + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t + +from ..http import parse_list_header + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyFix: + """Adjust the WSGI environ based on ``X-Forwarded-`` that proxies in + front of the application may set. + + - ``X-Forwarded-For`` sets ``REMOTE_ADDR``. + - ``X-Forwarded-Proto`` sets ``wsgi.url_scheme``. + - ``X-Forwarded-Host`` sets ``HTTP_HOST``, ``SERVER_NAME``, and + ``SERVER_PORT``. + - ``X-Forwarded-Port`` sets ``HTTP_HOST`` and ``SERVER_PORT``. + - ``X-Forwarded-Prefix`` sets ``SCRIPT_NAME``. + + You must tell the middleware how many proxies set each header so it + knows what values to trust. It is a security issue to trust values + that came from the client rather than a proxy. + + The original values of the headers are stored in the WSGI + environ as ``werkzeug.proxy_fix.orig``, a dict. + + :param app: The WSGI application to wrap. + :param x_for: Number of values to trust for ``X-Forwarded-For``. + :param x_proto: Number of values to trust for ``X-Forwarded-Proto``. + :param x_host: Number of values to trust for ``X-Forwarded-Host``. + :param x_port: Number of values to trust for ``X-Forwarded-Port``. + :param x_prefix: Number of values to trust for + ``X-Forwarded-Prefix``. + + .. code-block:: python + + from werkzeug.middleware.proxy_fix import ProxyFix + # App is behind one proxy that sets the -For and -Host headers. + app = ProxyFix(app, x_for=1, x_host=1) + + .. versionchanged:: 1.0 + Deprecated code has been removed: + + * The ``num_proxies`` argument and attribute. + * The ``get_remote_addr`` method. + * The environ keys ``orig_remote_addr``, + ``orig_wsgi_url_scheme``, and ``orig_http_host``. + + .. versionchanged:: 0.15 + All headers support multiple values. The ``num_proxies`` + argument is deprecated. Each header is configured with a + separate number of trusted proxies. + + .. versionchanged:: 0.15 + Original WSGI environ values are stored in the + ``werkzeug.proxy_fix.orig`` dict. ``orig_remote_addr``, + ``orig_wsgi_url_scheme``, and ``orig_http_host`` are deprecated + and will be removed in 1.0. + + .. versionchanged:: 0.15 + Support ``X-Forwarded-Port`` and ``X-Forwarded-Prefix``. + + .. versionchanged:: 0.15 + ``X-Forwarded-Host`` and ``X-Forwarded-Port`` modify + ``SERVER_NAME`` and ``SERVER_PORT``. + """ + + def __init__( + self, + app: "WSGIApplication", + x_for: int = 1, + x_proto: int = 1, + x_host: int = 0, + x_port: int = 0, + x_prefix: int = 0, + ) -> None: + self.app = app + self.x_for = x_for + self.x_proto = x_proto + self.x_host = x_host + self.x_port = x_port + self.x_prefix = x_prefix + + def _get_real_value(self, trusted: int, value: t.Optional[str]) -> t.Optional[str]: + """Get the real value from a list header based on the configured + number of trusted proxies. + + :param trusted: Number of values to trust in the header. + :param value: Comma separated list header value to parse. + :return: The real value, or ``None`` if there are fewer values + than the number of trusted proxies. + + .. versionchanged:: 1.0 + Renamed from ``_get_trusted_comma``. + + .. versionadded:: 0.15 + """ + if not (trusted and value): + return None + values = parse_list_header(value) + if len(values) >= trusted: + return values[-trusted] + return None + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Modify the WSGI environ based on the various ``Forwarded`` + headers before calling the wrapped application. Store the + original environ values in ``werkzeug.proxy_fix.orig_{key}``. + """ + environ_get = environ.get + orig_remote_addr = environ_get("REMOTE_ADDR") + orig_wsgi_url_scheme = environ_get("wsgi.url_scheme") + orig_http_host = environ_get("HTTP_HOST") + environ.update( + { + "werkzeug.proxy_fix.orig": { + "REMOTE_ADDR": orig_remote_addr, + "wsgi.url_scheme": orig_wsgi_url_scheme, + "HTTP_HOST": orig_http_host, + "SERVER_NAME": environ_get("SERVER_NAME"), + "SERVER_PORT": environ_get("SERVER_PORT"), + "SCRIPT_NAME": environ_get("SCRIPT_NAME"), + } + } + ) + + x_for = self._get_real_value(self.x_for, environ_get("HTTP_X_FORWARDED_FOR")) + if x_for: + environ["REMOTE_ADDR"] = x_for + + x_proto = self._get_real_value( + self.x_proto, environ_get("HTTP_X_FORWARDED_PROTO") + ) + if x_proto: + environ["wsgi.url_scheme"] = x_proto + + x_host = self._get_real_value(self.x_host, environ_get("HTTP_X_FORWARDED_HOST")) + if x_host: + environ["HTTP_HOST"] = environ["SERVER_NAME"] = x_host + # "]" to check for IPv6 address without port + if ":" in x_host and not x_host.endswith("]"): + environ["SERVER_NAME"], environ["SERVER_PORT"] = x_host.rsplit(":", 1) + + x_port = self._get_real_value(self.x_port, environ_get("HTTP_X_FORWARDED_PORT")) + if x_port: + host = environ.get("HTTP_HOST") + if host: + # "]" to check for IPv6 address without port + if ":" in host and not host.endswith("]"): + host = host.rsplit(":", 1)[0] + environ["HTTP_HOST"] = f"{host}:{x_port}" + environ["SERVER_PORT"] = x_port + + x_prefix = self._get_real_value( + self.x_prefix, environ_get("HTTP_X_FORWARDED_PREFIX") + ) + if x_prefix: + environ["SCRIPT_NAME"] = x_prefix + + return self.app(environ, start_response) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py new file mode 100644 index 0000000..2ec396c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py @@ -0,0 +1,280 @@ +""" +Serve Shared Static Files +========================= + +.. autoclass:: SharedDataMiddleware + :members: is_allowed + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import mimetypes +import os +import pkgutil +import posixpath +import typing as t +from datetime import datetime +from datetime import timezone +from io import BytesIO +from time import time +from zlib import adler32 + +from ..http import http_date +from ..http import is_resource_modified +from ..security import safe_join +from ..utils import get_content_type +from ..wsgi import get_path_info +from ..wsgi import wrap_file + +_TOpener = t.Callable[[], t.Tuple[t.IO[bytes], datetime, int]] +_TLoader = t.Callable[[t.Optional[str]], t.Tuple[t.Optional[str], t.Optional[_TOpener]]] + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class SharedDataMiddleware: + + """A WSGI middleware which provides static content for development + environments or simple server setups. Its usage is quite simple:: + + import os + from werkzeug.middleware.shared_data import SharedDataMiddleware + + app = SharedDataMiddleware(app, { + '/shared': os.path.join(os.path.dirname(__file__), 'shared') + }) + + The contents of the folder ``./shared`` will now be available on + ``http://example.com/shared/``. This is pretty useful during development + because a standalone media server is not required. Files can also be + mounted on the root folder and still continue to use the application because + the shared data middleware forwards all unhandled requests to the + application, even if the requests are below one of the shared folders. + + If `pkg_resources` is available you can also tell the middleware to serve + files from package data:: + + app = SharedDataMiddleware(app, { + '/static': ('myapplication', 'static') + }) + + This will then serve the ``static`` folder in the `myapplication` + Python package. + + The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch` + rules for files that are not accessible from the web. If `cache` is set to + `False` no caching headers are sent. + + Currently the middleware does not support non-ASCII filenames. If the + encoding on the file system happens to match the encoding of the URI it may + work but this could also be by accident. We strongly suggest using ASCII + only file names for static files. + + The middleware will guess the mimetype using the Python `mimetype` + module. If it's unable to figure out the charset it will fall back + to `fallback_mimetype`. + + :param app: the application to wrap. If you don't want to wrap an + application you can pass it :exc:`NotFound`. + :param exports: a list or dict of exported files and folders. + :param disallow: a list of :func:`~fnmatch.fnmatch` rules. + :param cache: enable or disable caching headers. + :param cache_timeout: the cache timeout in seconds for the headers. + :param fallback_mimetype: The fallback mimetype for unknown files. + + .. versionchanged:: 1.0 + The default ``fallback_mimetype`` is + ``application/octet-stream``. If a filename looks like a text + mimetype, the ``utf-8`` charset is added to it. + + .. versionadded:: 0.6 + Added ``fallback_mimetype``. + + .. versionchanged:: 0.5 + Added ``cache_timeout``. + """ + + def __init__( + self, + app: "WSGIApplication", + exports: t.Union[ + t.Dict[str, t.Union[str, t.Tuple[str, str]]], + t.Iterable[t.Tuple[str, t.Union[str, t.Tuple[str, str]]]], + ], + disallow: None = None, + cache: bool = True, + cache_timeout: int = 60 * 60 * 12, + fallback_mimetype: str = "application/octet-stream", + ) -> None: + self.app = app + self.exports: t.List[t.Tuple[str, _TLoader]] = [] + self.cache = cache + self.cache_timeout = cache_timeout + + if isinstance(exports, dict): + exports = exports.items() + + for key, value in exports: + if isinstance(value, tuple): + loader = self.get_package_loader(*value) + elif isinstance(value, str): + if os.path.isfile(value): + loader = self.get_file_loader(value) + else: + loader = self.get_directory_loader(value) + else: + raise TypeError(f"unknown def {value!r}") + + self.exports.append((key, loader)) + + if disallow is not None: + from fnmatch import fnmatch + + self.is_allowed = lambda x: not fnmatch(x, disallow) + + self.fallback_mimetype = fallback_mimetype + + def is_allowed(self, filename: str) -> bool: + """Subclasses can override this method to disallow the access to + certain files. However by providing `disallow` in the constructor + this method is overwritten. + """ + return True + + def _opener(self, filename: str) -> _TOpener: + return lambda: ( + open(filename, "rb"), + datetime.fromtimestamp(os.path.getmtime(filename), tz=timezone.utc), + int(os.path.getsize(filename)), + ) + + def get_file_loader(self, filename: str) -> _TLoader: + return lambda x: (os.path.basename(filename), self._opener(filename)) + + def get_package_loader(self, package: str, package_path: str) -> _TLoader: + load_time = datetime.now(timezone.utc) + provider = pkgutil.get_loader(package) + reader = provider.get_resource_reader(package) # type: ignore + + def loader( + path: t.Optional[str], + ) -> t.Tuple[t.Optional[str], t.Optional[_TOpener]]: + if path is None: + return None, None + + path = safe_join(package_path, path) + + if path is None: + return None, None + + basename = posixpath.basename(path) + + try: + resource = reader.open_resource(path) + except OSError: + return None, None + + if isinstance(resource, BytesIO): + return ( + basename, + lambda: (resource, load_time, len(resource.getvalue())), + ) + + return ( + basename, + lambda: ( + resource, + datetime.fromtimestamp( + os.path.getmtime(resource.name), tz=timezone.utc + ), + os.path.getsize(resource.name), + ), + ) + + return loader + + def get_directory_loader(self, directory: str) -> _TLoader: + def loader( + path: t.Optional[str], + ) -> t.Tuple[t.Optional[str], t.Optional[_TOpener]]: + if path is not None: + path = safe_join(directory, path) + + if path is None: + return None, None + else: + path = directory + + if os.path.isfile(path): + return os.path.basename(path), self._opener(path) + + return None, None + + return loader + + def generate_etag(self, mtime: datetime, file_size: int, real_filename: str) -> str: + real_filename = os.fsencode(real_filename) + timestamp = mtime.timestamp() + checksum = adler32(real_filename) & 0xFFFFFFFF + return f"wzsdm-{timestamp}-{file_size}-{checksum}" + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + path = get_path_info(environ) + file_loader = None + + for search_path, loader in self.exports: + if search_path == path: + real_filename, file_loader = loader(None) + + if file_loader is not None: + break + + if not search_path.endswith("/"): + search_path += "/" + + if path.startswith(search_path): + real_filename, file_loader = loader(path[len(search_path) :]) + + if file_loader is not None: + break + + if file_loader is None or not self.is_allowed(real_filename): # type: ignore + return self.app(environ, start_response) + + guessed_type = mimetypes.guess_type(real_filename) # type: ignore + mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype, "utf-8") + f, mtime, file_size = file_loader() + + headers = [("Date", http_date())] + + if self.cache: + timeout = self.cache_timeout + etag = self.generate_etag(mtime, file_size, real_filename) # type: ignore + headers += [ + ("Etag", f'"{etag}"'), + ("Cache-Control", f"max-age={timeout}, public"), + ] + + if not is_resource_modified(environ, etag, last_modified=mtime): + f.close() + start_response("304 Not Modified", headers) + return [] + + headers.append(("Expires", http_date(time() + timeout))) + else: + headers.append(("Cache-Control", "public")) + + headers.extend( + ( + ("Content-Type", mime_type), + ("Content-Length", str(file_size)), + ("Last-Modified", http_date(mtime)), + ) + ) + start_response("200 OK", headers) + return wrap_file(environ, f) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/py.typed b/axios-example/lib/python3.10/site-packages/werkzeug/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/routing.py b/axios-example/lib/python3.10/site-packages/werkzeug/routing.py new file mode 100644 index 0000000..1d3027b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/routing.py @@ -0,0 +1,2332 @@ +"""When it comes to combining multiple controller or view functions +(however you want to call them) you need a dispatcher. A simple way +would be applying regular expression tests on the ``PATH_INFO`` and +calling registered callback functions that return the value then. + +This module implements a much more powerful system than simple regular +expression matching because it can also convert values in the URLs and +build URLs. + +Here a simple example that creates a URL map for an application with +two subdomains (www and kb) and some URL rules: + +.. code-block:: python + + m = Map([ + # Static URLs + Rule('/', endpoint='static/index'), + Rule('/about', endpoint='static/about'), + Rule('/help', endpoint='static/help'), + # Knowledge Base + Subdomain('kb', [ + Rule('/', endpoint='kb/index'), + Rule('/browse/', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse') + ]) + ], default_subdomain='www') + +If the application doesn't use subdomains it's perfectly fine to not set +the default subdomain and not use the `Subdomain` rule factory. The +endpoint in the rules can be anything, for example import paths or +unique identifiers. The WSGI application can use those endpoints to get the +handler for that URL. It doesn't have to be a string at all but it's +recommended. + +Now it's possible to create a URL adapter for one of the subdomains and +build URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.build("kb/browse", dict(id=42)) + 'http://kb.example.com/browse/42/' + + c.build("kb/browse", dict()) + 'http://kb.example.com/browse/' + + c.build("kb/browse", dict(id=42, page=3)) + 'http://kb.example.com/browse/42/3' + + c.build("static/about") + '/about' + + c.build("static/index", force_external=True) + 'http://www.example.com/' + + c = m.bind('example.com', subdomain='kb') + + c.build("static/about") + 'http://www.example.com/about' + +The first argument to bind is the server name *without* the subdomain. +Per default it will assume that the script is mounted on the root, but +often that's not the case so you can provide the real mount point as +second argument: + +.. code-block:: python + + c = m.bind('example.com', '/applications/example') + +The third argument can be the subdomain, if not given the default +subdomain is used. For more details about binding have a look at the +documentation of the `MapAdapter`. + +And here is how you can match URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.match("/") + ('static/index', {}) + + c.match("/about") + ('static/about', {}) + + c = m.bind('example.com', '/', 'kb') + + c.match("/") + ('kb/index', {}) + + c.match("/browse/42/23") + ('kb/browse', {'id': 42, 'page': 23}) + +If matching fails you get a ``NotFound`` exception, if the rule thinks +it's a good idea to redirect (for example because the URL was defined +to have a slash at the end but the request was missing that slash) it +will raise a ``RequestRedirect`` exception. Both are subclasses of +``HTTPException`` so you can use those errors as responses in the +application. + +If matching succeeded but the URL rule was incompatible to the given +method (for example there were only rules for ``GET`` and ``HEAD`` but +routing tried to match a ``POST`` request) a ``MethodNotAllowed`` +exception is raised. +""" +import ast +import difflib +import posixpath +import re +import typing +import typing as t +import uuid +import warnings +from pprint import pformat +from string import Template +from threading import Lock +from types import CodeType + +from ._internal import _encode_idna +from ._internal import _get_environ +from ._internal import _to_bytes +from ._internal import _to_str +from ._internal import _wsgi_decoding_dance +from .datastructures import ImmutableDict +from .datastructures import MultiDict +from .exceptions import BadHost +from .exceptions import BadRequest +from .exceptions import HTTPException +from .exceptions import MethodNotAllowed +from .exceptions import NotFound +from .urls import _fast_url_quote +from .urls import url_encode +from .urls import url_join +from .urls import url_quote +from .urls import url_unquote +from .utils import cached_property +from .utils import redirect +from .wsgi import get_host + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from .wrappers.request import Request + from .wrappers.response import Response + +_rule_re = re.compile( + r""" + (?P[^<]*) # static rule data + < + (?: + (?P[a-zA-Z_][a-zA-Z0-9_]*) # converter name + (?:\((?P.*?)\))? # converter arguments + \: # variable delimiter + )? + (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name + > + """, + re.VERBOSE, +) +_simple_rule_re = re.compile(r"<([^>]+)>") +_converter_args_re = re.compile( + r""" + ((?P\w+)\s*=\s*)? + (?P + True|False| + \d+.\d+| + \d+.| + \d+| + [\w\d_.]+| + [urUR]?(?P"[^"]*?"|'[^']*') + )\s*, + """, + re.VERBOSE, +) + + +_PYTHON_CONSTANTS = {"None": None, "True": True, "False": False} + + +def _pythonize(value: str) -> t.Union[None, bool, int, float, str]: + if value in _PYTHON_CONSTANTS: + return _PYTHON_CONSTANTS[value] + for convert in int, float: + try: + return convert(value) # type: ignore + except ValueError: + pass + if value[:1] == value[-1:] and value[0] in "\"'": + value = value[1:-1] + return str(value) + + +def parse_converter_args(argstr: str) -> t.Tuple[t.Tuple, t.Dict[str, t.Any]]: + argstr += "," + args = [] + kwargs = {} + + for item in _converter_args_re.finditer(argstr): + value = item.group("stringval") + if value is None: + value = item.group("value") + value = _pythonize(value) + if not item.group("name"): + args.append(value) + else: + name = item.group("name") + kwargs[name] = value + + return tuple(args), kwargs + + +def parse_rule(rule: str) -> t.Iterator[t.Tuple[t.Optional[str], t.Optional[str], str]]: + """Parse a rule and return it as generator. Each iteration yields tuples + in the form ``(converter, arguments, variable)``. If the converter is + `None` it's a static url part, otherwise it's a dynamic one. + + :internal: + """ + pos = 0 + end = len(rule) + do_match = _rule_re.match + used_names = set() + while pos < end: + m = do_match(rule, pos) + if m is None: + break + data = m.groupdict() + if data["static"]: + yield None, None, data["static"] + variable = data["variable"] + converter = data["converter"] or "default" + if variable in used_names: + raise ValueError(f"variable name {variable!r} used twice.") + used_names.add(variable) + yield converter, data["args"] or None, variable + pos = m.end() + if pos < end: + remaining = rule[pos:] + if ">" in remaining or "<" in remaining: + raise ValueError(f"malformed url rule: {rule!r}") + yield None, None, remaining + + +class RoutingException(Exception): + """Special exceptions that require the application to redirect, notifying + about missing urls, etc. + + :internal: + """ + + +class RequestRedirect(HTTPException, RoutingException): + """Raise if the map requests a redirect. This is for example the case if + `strict_slashes` are activated and an url that requires a trailing slash. + + The attribute `new_url` contains the absolute destination url. + """ + + code = 308 + + def __init__(self, new_url: str) -> None: + super().__init__(new_url) + self.new_url = new_url + + def get_response( + self, + environ: t.Optional[t.Union["WSGIEnvironment", "Request"]] = None, + scope: t.Optional[dict] = None, + ) -> "Response": + return redirect(self.new_url, self.code) + + +class RequestPath(RoutingException): + """Internal exception.""" + + __slots__ = ("path_info",) + + def __init__(self, path_info: str) -> None: + super().__init__() + self.path_info = path_info + + +class RequestAliasRedirect(RoutingException): # noqa: B903 + """This rule is an alias and wants to redirect to the canonical URL.""" + + def __init__(self, matched_values: t.Mapping[str, t.Any]) -> None: + super().__init__() + self.matched_values = matched_values + + +class BuildError(RoutingException, LookupError): + """Raised if the build system cannot find a URL for an endpoint with the + values provided. + """ + + def __init__( + self, + endpoint: str, + values: t.Mapping[str, t.Any], + method: t.Optional[str], + adapter: t.Optional["MapAdapter"] = None, + ) -> None: + super().__init__(endpoint, values, method) + self.endpoint = endpoint + self.values = values + self.method = method + self.adapter = adapter + + @cached_property + def suggested(self) -> t.Optional["Rule"]: + return self.closest_rule(self.adapter) + + def closest_rule(self, adapter: t.Optional["MapAdapter"]) -> t.Optional["Rule"]: + def _score_rule(rule: "Rule") -> float: + return sum( + [ + 0.98 + * difflib.SequenceMatcher( + None, rule.endpoint, self.endpoint + ).ratio(), + 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), + 0.01 * bool(rule.methods and self.method in rule.methods), + ] + ) + + if adapter and adapter.map._rules: + return max(adapter.map._rules, key=_score_rule) + + return None + + def __str__(self) -> str: + message = [f"Could not build url for endpoint {self.endpoint!r}"] + if self.method: + message.append(f" ({self.method!r})") + if self.values: + message.append(f" with values {sorted(self.values)!r}") + message.append(".") + if self.suggested: + if self.endpoint == self.suggested.endpoint: + if ( + self.method + and self.suggested.methods is not None + and self.method not in self.suggested.methods + ): + message.append( + " Did you mean to use methods" + f" {sorted(self.suggested.methods)!r}?" + ) + missing_values = self.suggested.arguments.union( + set(self.suggested.defaults or ()) + ) - set(self.values.keys()) + if missing_values: + message.append( + f" Did you forget to specify values {sorted(missing_values)!r}?" + ) + else: + message.append(f" Did you mean {self.suggested.endpoint!r} instead?") + return "".join(message) + + +class WebsocketMismatch(BadRequest): + """The only matched rule is either a WebSocket and the request is + HTTP, or the rule is HTTP and the request is a WebSocket. + """ + + +class ValidationError(ValueError): + """Validation error. If a rule converter raises this exception the rule + does not match the current URL and the next URL is tried. + """ + + +class RuleFactory: + """As soon as you have more complex URL setups it's a good idea to use rule + factories to avoid repetitive tasks. Some of them are builtin, others can + be added by subclassing `RuleFactory` and overriding `get_rules`. + """ + + def get_rules(self, map: "Map") -> t.Iterable["Rule"]: + """Subclasses of `RuleFactory` have to override this method and return + an iterable of rules.""" + raise NotImplementedError() + + +class Subdomain(RuleFactory): + """All URLs provided by this factory have the subdomain set to a + specific domain. For example if you want to use the subdomain for + the current language this can be a good setup:: + + url_map = Map([ + Rule('/', endpoint='#select_language'), + Subdomain('', [ + Rule('/', endpoint='index'), + Rule('/about', endpoint='about'), + Rule('/help', endpoint='help') + ]) + ]) + + All the rules except for the ``'#select_language'`` endpoint will now + listen on a two letter long subdomain that holds the language code + for the current request. + """ + + def __init__(self, subdomain: str, rules: t.Iterable[RuleFactory]) -> None: + self.subdomain = subdomain + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.subdomain = self.subdomain + yield rule + + +class Submount(RuleFactory): + """Like `Subdomain` but prefixes the URL rule with a given string:: + + url_map = Map([ + Rule('/', endpoint='index'), + Submount('/blog', [ + Rule('/', endpoint='blog/index'), + Rule('/entry/', endpoint='blog/show') + ]) + ]) + + Now the rule ``'blog/show'`` matches ``/blog/entry/``. + """ + + def __init__(self, path: str, rules: t.Iterable[RuleFactory]) -> None: + self.path = path.rstrip("/") + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.rule = self.path + rule.rule + yield rule + + +class EndpointPrefix(RuleFactory): + """Prefixes all endpoints (which must be strings for this factory) with + another string. This can be useful for sub applications:: + + url_map = Map([ + Rule('/', endpoint='index'), + EndpointPrefix('blog/', [Submount('/blog', [ + Rule('/', endpoint='index'), + Rule('/entry/', endpoint='show') + ])]) + ]) + """ + + def __init__(self, prefix: str, rules: t.Iterable[RuleFactory]) -> None: + self.prefix = prefix + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.endpoint = self.prefix + rule.endpoint + yield rule + + +class RuleTemplate: + """Returns copies of the rules wrapped and expands string templates in + the endpoint, rule, defaults or subdomain sections. + + Here a small example for such a rule template:: + + from werkzeug.routing import Map, Rule, RuleTemplate + + resource = RuleTemplate([ + Rule('/$name/', endpoint='$name.list'), + Rule('/$name/', endpoint='$name.show') + ]) + + url_map = Map([resource(name='user'), resource(name='page')]) + + When a rule template is called the keyword arguments are used to + replace the placeholders in all the string parameters. + """ + + def __init__(self, rules: t.Iterable["Rule"]) -> None: + self.rules = list(rules) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> "RuleTemplateFactory": + return RuleTemplateFactory(self.rules, dict(*args, **kwargs)) + + +class RuleTemplateFactory(RuleFactory): + """A factory that fills in template variables into rules. Used by + `RuleTemplate` internally. + + :internal: + """ + + def __init__( + self, rules: t.Iterable[RuleFactory], context: t.Dict[str, t.Any] + ) -> None: + self.rules = rules + self.context = context + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + new_defaults = subdomain = None + if rule.defaults: + new_defaults = {} + for key, value in rule.defaults.items(): + if isinstance(value, str): + value = Template(value).substitute(self.context) + new_defaults[key] = value + if rule.subdomain is not None: + subdomain = Template(rule.subdomain).substitute(self.context) + new_endpoint = rule.endpoint + if isinstance(new_endpoint, str): + new_endpoint = Template(new_endpoint).substitute(self.context) + yield Rule( + Template(rule.rule).substitute(self.context), + new_defaults, + subdomain, + rule.methods, + rule.build_only, + new_endpoint, + rule.strict_slashes, + ) + + +def _prefix_names(src: str) -> ast.stmt: + """ast parse and prefix names with `.` to avoid collision with user vars""" + tree = ast.parse(src).body[0] + if isinstance(tree, ast.Expr): + tree = tree.value # type: ignore + for node in ast.walk(tree): + if isinstance(node, ast.Name): + node.id = f".{node.id}" + return tree + + +_CALL_CONVERTER_CODE_FMT = "self._converters[{elem!r}].to_url()" +_IF_KWARGS_URL_ENCODE_CODE = """\ +if kwargs: + params = self._encode_query_vars(kwargs) + q = "?" if params else "" +else: + q = params = "" +""" +_IF_KWARGS_URL_ENCODE_AST = _prefix_names(_IF_KWARGS_URL_ENCODE_CODE) +_URL_ENCODE_AST_NAMES = (_prefix_names("q"), _prefix_names("params")) + + +class Rule(RuleFactory): + """A Rule represents one URL pattern. There are some options for `Rule` + that change the way it behaves and are passed to the `Rule` constructor. + Note that besides the rule-string all arguments *must* be keyword arguments + in order to not break the application on Werkzeug upgrades. + + `string` + Rule strings basically are just normal URL paths with placeholders in + the format ```` where the converter and the + arguments are optional. If no converter is defined the `default` + converter is used which means `string` in the normal configuration. + + URL rules that end with a slash are branch URLs, others are leaves. + If you have `strict_slashes` enabled (which is the default), all + branch URLs that are matched without a trailing slash will trigger a + redirect to the same URL with the missing slash appended. + + The converters are defined on the `Map`. + + `endpoint` + The endpoint for this rule. This can be anything. A reference to a + function, a string, a number etc. The preferred way is using a string + because the endpoint is used for URL generation. + + `defaults` + An optional dict with defaults for other rules with the same endpoint. + This is a bit tricky but useful if you want to have unique URLs:: + + url_map = Map([ + Rule('/all/', defaults={'page': 1}, endpoint='all_entries'), + Rule('/all/page/', endpoint='all_entries') + ]) + + If a user now visits ``http://example.com/all/page/1`` they will be + redirected to ``http://example.com/all/``. If `redirect_defaults` is + disabled on the `Map` instance this will only affect the URL + generation. + + `subdomain` + The subdomain rule string for this rule. If not specified the rule + only matches for the `default_subdomain` of the map. If the map is + not bound to a subdomain this feature is disabled. + + Can be useful if you want to have user profiles on different subdomains + and all subdomains are forwarded to your application:: + + url_map = Map([ + Rule('/', subdomain='', endpoint='user/homepage'), + Rule('/stats', subdomain='', endpoint='user/stats') + ]) + + `methods` + A sequence of http methods this rule applies to. If not specified, all + methods are allowed. For example this can be useful if you want different + endpoints for `POST` and `GET`. If methods are defined and the path + matches but the method matched against is not in this list or in the + list of another rule for that path the error raised is of the type + `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the + list of methods and `HEAD` is not, `HEAD` is added automatically. + + `strict_slashes` + Override the `Map` setting for `strict_slashes` only for this rule. If + not specified the `Map` setting is used. + + `merge_slashes` + Override :attr:`Map.merge_slashes` for this rule. + + `build_only` + Set this to True and the rule will never match but will create a URL + that can be build. This is useful if you have resources on a subdomain + or folder that are not handled by the WSGI application (like static data) + + `redirect_to` + If given this must be either a string or callable. In case of a + callable it's called with the url adapter that triggered the match and + the values of the URL as keyword arguments and has to return the target + for the redirect, otherwise it has to be a string with placeholders in + rule syntax:: + + def foo_with_slug(adapter, id): + # ask the database for the slug for the old id. this of + # course has nothing to do with werkzeug. + return f'foo/{Foo.get_slug_for_id(id)}' + + url_map = Map([ + Rule('/foo/', endpoint='foo'), + Rule('/some/old/url/', redirect_to='foo/'), + Rule('/other/old/url/', redirect_to=foo_with_slug) + ]) + + When the rule is matched the routing system will raise a + `RequestRedirect` exception with the target for the redirect. + + Keep in mind that the URL will be joined against the URL root of the + script so don't use a leading slash on the target URL unless you + really mean root of that domain. + + `alias` + If enabled this rule serves as an alias for another rule with the same + endpoint and arguments. + + `host` + If provided and the URL map has host matching enabled this can be + used to provide a match rule for the whole host. This also means + that the subdomain feature is disabled. + + `websocket` + If ``True``, this rule is only matches for WebSocket (``ws://``, + ``wss://``) requests. By default, rules will only match for HTTP + requests. + + .. versionchanged:: 2.1 + Percent-encoded newlines (``%0a``), which are decoded by WSGI + servers, are considered when routing instead of terminating the + match early. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionadded:: 1.0 + Added ``merge_slashes``. + + .. versionadded:: 0.7 + Added ``alias`` and ``host``. + + .. versionchanged:: 0.6.1 + ``HEAD`` is added to ``methods`` if ``GET`` is present. + """ + + def __init__( + self, + string: str, + defaults: t.Optional[t.Mapping[str, t.Any]] = None, + subdomain: t.Optional[str] = None, + methods: t.Optional[t.Iterable[str]] = None, + build_only: bool = False, + endpoint: t.Optional[str] = None, + strict_slashes: t.Optional[bool] = None, + merge_slashes: t.Optional[bool] = None, + redirect_to: t.Optional[t.Union[str, t.Callable[..., str]]] = None, + alias: bool = False, + host: t.Optional[str] = None, + websocket: bool = False, + ) -> None: + if not string.startswith("/"): + raise ValueError("urls must start with a leading slash") + self.rule = string + self.is_leaf = not string.endswith("/") + + self.map: "Map" = None # type: ignore + self.strict_slashes = strict_slashes + self.merge_slashes = merge_slashes + self.subdomain = subdomain + self.host = host + self.defaults = defaults + self.build_only = build_only + self.alias = alias + self.websocket = websocket + + if methods is not None: + if isinstance(methods, str): + raise TypeError("'methods' should be a list of strings.") + + methods = {x.upper() for x in methods} + + if "HEAD" not in methods and "GET" in methods: + methods.add("HEAD") + + if websocket and methods - {"GET", "HEAD", "OPTIONS"}: + raise ValueError( + "WebSocket rules can only use 'GET', 'HEAD', and 'OPTIONS' methods." + ) + + self.methods = methods + self.endpoint: str = endpoint # type: ignore + self.redirect_to = redirect_to + + if defaults: + self.arguments = set(map(str, defaults)) + else: + self.arguments = set() + + self._trace: t.List[t.Tuple[bool, str]] = [] + + def empty(self) -> "Rule": + """ + Return an unbound copy of this rule. + + This can be useful if want to reuse an already bound URL for another + map. See ``get_empty_kwargs`` to override what keyword arguments are + provided to the new copy. + """ + return type(self)(self.rule, **self.get_empty_kwargs()) + + def get_empty_kwargs(self) -> t.Mapping[str, t.Any]: + """ + Provides kwargs for instantiating empty copy with empty() + + Use this method to provide custom keyword arguments to the subclass of + ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass + has custom keyword arguments that are needed at instantiation. + + Must return a ``dict`` that will be provided as kwargs to the new + instance of ``Rule``, following the initial ``self.rule`` value which + is always provided as the first, required positional argument. + """ + defaults = None + if self.defaults: + defaults = dict(self.defaults) + return dict( + defaults=defaults, + subdomain=self.subdomain, + methods=self.methods, + build_only=self.build_only, + endpoint=self.endpoint, + strict_slashes=self.strict_slashes, + redirect_to=self.redirect_to, + alias=self.alias, + host=self.host, + ) + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + yield self + + def refresh(self) -> None: + """Rebinds and refreshes the URL. Call this if you modified the + rule in place. + + :internal: + """ + self.bind(self.map, rebind=True) + + def bind(self, map: "Map", rebind: bool = False) -> None: + """Bind the url to a map and create a regular expression based on + the information from the rule itself and the defaults from the map. + + :internal: + """ + if self.map is not None and not rebind: + raise RuntimeError(f"url rule {self!r} already bound to map {self.map!r}") + self.map = map + if self.strict_slashes is None: + self.strict_slashes = map.strict_slashes + if self.merge_slashes is None: + self.merge_slashes = map.merge_slashes + if self.subdomain is None: + self.subdomain = map.default_subdomain + self.compile() + + def get_converter( + self, + variable_name: str, + converter_name: str, + args: t.Tuple, + kwargs: t.Mapping[str, t.Any], + ) -> "BaseConverter": + """Looks up the converter for the given parameter. + + .. versionadded:: 0.9 + """ + if converter_name not in self.map.converters: + raise LookupError(f"the converter {converter_name!r} does not exist") + return self.map.converters[converter_name](self.map, *args, **kwargs) + + def _encode_query_vars(self, query_vars: t.Mapping[str, t.Any]) -> str: + return url_encode( + query_vars, + charset=self.map.charset, + sort=self.map.sort_parameters, + key=self.map.sort_key, + ) + + def compile(self) -> None: + """Compiles the regular expression and stores it.""" + assert self.map is not None, "rule not bound" + + if self.map.host_matching: + domain_rule = self.host or "" + else: + domain_rule = self.subdomain or "" + + self._trace = [] + self._converters: t.Dict[str, "BaseConverter"] = {} + self._static_weights: t.List[t.Tuple[int, int]] = [] + self._argument_weights: t.List[int] = [] + regex_parts = [] + + def _build_regex(rule: str) -> None: + index = 0 + for converter, arguments, variable in parse_rule(rule): + if converter is None: + for match in re.finditer(r"/+|[^/]+", variable): + part = match.group(0) + if part.startswith("/"): + if self.merge_slashes: + regex_parts.append(r"/+?") + self._trace.append((False, "/")) + else: + regex_parts.append(part) + self._trace.append((False, part)) + continue + self._trace.append((False, part)) + regex_parts.append(re.escape(part)) + if part: + self._static_weights.append((index, -len(part))) + else: + if arguments: + c_args, c_kwargs = parse_converter_args(arguments) + else: + c_args = () + c_kwargs = {} + convobj = self.get_converter(variable, converter, c_args, c_kwargs) + regex_parts.append(f"(?P<{variable}>{convobj.regex})") + self._converters[variable] = convobj + self._trace.append((True, variable)) + self._argument_weights.append(convobj.weight) + self.arguments.add(str(variable)) + index = index + 1 + + _build_regex(domain_rule) + regex_parts.append("\\|") + self._trace.append((False, "|")) + _build_regex(self.rule if self.is_leaf else self.rule.rstrip("/")) + if not self.is_leaf: + self._trace.append((False, "/")) + + self._build: t.Callable[..., t.Tuple[str, str]] + self._build = self._compile_builder(False).__get__(self, None) + self._build_unknown: t.Callable[..., t.Tuple[str, str]] + self._build_unknown = self._compile_builder(True).__get__(self, None) + + if self.build_only: + return + + if not (self.is_leaf and self.strict_slashes): + reps = "*" if self.merge_slashes else "?" + tail = f"(?/{reps})" + else: + tail = "" + + # Use \Z instead of $ to avoid matching before a %0a decoded to + # a \n by WSGI. + regex = rf"^{''.join(regex_parts)}{tail}$\Z" + self._regex = re.compile(regex) + + def match( + self, path: str, method: t.Optional[str] = None + ) -> t.Optional[t.MutableMapping[str, t.Any]]: + """Check if the rule matches a given path. Path is a string in the + form ``"subdomain|/path"`` and is assembled by the map. If + the map is doing host matching the subdomain part will be the host + instead. + + If the rule matches a dict with the converted values is returned, + otherwise the return value is `None`. + + :internal: + """ + if not self.build_only: + require_redirect = False + + m = self._regex.search(path) + if m is not None: + groups = m.groupdict() + # we have a folder like part of the url without a trailing + # slash and strict slashes enabled. raise an exception that + # tells the map to redirect to the same url but with a + # trailing slash + if ( + self.strict_slashes + and not self.is_leaf + and not groups.pop("__suffix__") + and ( + method is None or self.methods is None or method in self.methods + ) + ): + path += "/" + require_redirect = True + # if we are not in strict slashes mode we have to remove + # a __suffix__ + elif not self.strict_slashes: + del groups["__suffix__"] + + result = {} + for name, value in groups.items(): + try: + value = self._converters[name].to_python(value) + except ValidationError: + return None + result[str(name)] = value + if self.defaults: + result.update(self.defaults) + + if self.merge_slashes: + new_path = "|".join(self.build(result, False)) # type: ignore + if path.endswith("/") and not new_path.endswith("/"): + new_path += "/" + if new_path.count("/") < path.count("/"): + # The URL will be encoded when MapAdapter.match + # handles the RequestPath raised below. Decode + # the URL here to avoid a double encoding. + path = url_unquote(new_path) + require_redirect = True + + if require_redirect: + path = path.split("|", 1)[1] + raise RequestPath(path) + + if self.alias and self.map.redirect_defaults: + raise RequestAliasRedirect(result) + + return result + + return None + + @staticmethod + def _get_func_code(code: CodeType, name: str) -> t.Callable[..., t.Tuple[str, str]]: + globs: t.Dict[str, t.Any] = {} + locs: t.Dict[str, t.Any] = {} + exec(code, globs, locs) + return locs[name] # type: ignore + + def _compile_builder( + self, append_unknown: bool = True + ) -> t.Callable[..., t.Tuple[str, str]]: + defaults = self.defaults or {} + dom_ops: t.List[t.Tuple[bool, str]] = [] + url_ops: t.List[t.Tuple[bool, str]] = [] + + opl = dom_ops + for is_dynamic, data in self._trace: + if data == "|" and opl is dom_ops: + opl = url_ops + continue + # this seems like a silly case to ever come up but: + # if a default is given for a value that appears in the rule, + # resolve it to a constant ahead of time + if is_dynamic and data in defaults: + data = self._converters[data].to_url(defaults[data]) + opl.append((False, data)) + elif not is_dynamic: + opl.append( + (False, url_quote(_to_bytes(data, self.map.charset), safe="/:|+")) + ) + else: + opl.append((True, data)) + + def _convert(elem: str) -> ast.stmt: + ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem)) + ret.args = [ast.Name(str(elem), ast.Load())] # type: ignore # str for py2 + return ret + + def _parts(ops: t.List[t.Tuple[bool, str]]) -> t.List[ast.AST]: + parts = [ + _convert(elem) if is_dynamic else ast.Str(s=elem) + for is_dynamic, elem in ops + ] + parts = parts or [ast.Str("")] + # constant fold + ret = [parts[0]] + for p in parts[1:]: + if isinstance(p, ast.Str) and isinstance(ret[-1], ast.Str): + ret[-1] = ast.Str(ret[-1].s + p.s) + else: + ret.append(p) + return ret + + dom_parts = _parts(dom_ops) + url_parts = _parts(url_ops) + if not append_unknown: + body = [] + else: + body = [_IF_KWARGS_URL_ENCODE_AST] + url_parts.extend(_URL_ENCODE_AST_NAMES) + + def _join(parts: t.List[ast.AST]) -> ast.AST: + if len(parts) == 1: # shortcut + return parts[0] + return ast.JoinedStr(parts) + + body.append( + ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())) + ) + + pargs = [ + elem + for is_dynamic, elem in dom_ops + url_ops + if is_dynamic and elem not in defaults + ] + kargs = [str(k) for k in defaults] + + func_ast: ast.FunctionDef = _prefix_names("def _(): pass") # type: ignore + func_ast.name = f"" + func_ast.args.args.append(ast.arg(".self", None)) + for arg in pargs + kargs: + func_ast.args.args.append(ast.arg(arg, None)) + func_ast.args.kwarg = ast.arg(".kwargs", None) + for _ in kargs: + func_ast.args.defaults.append(ast.Str("")) + func_ast.body = body + + # use `ast.parse` instead of `ast.Module` for better portability + # Python 3.8 changes the signature of `ast.Module` + module = ast.parse("") + module.body = [func_ast] + + # mark everything as on line 1, offset 0 + # less error-prone than `ast.fix_missing_locations` + # bad line numbers cause an assert to fail in debug builds + for node in ast.walk(module): + if "lineno" in node._attributes: + node.lineno = 1 + if "col_offset" in node._attributes: + node.col_offset = 0 + + code = compile(module, "", "exec") + return self._get_func_code(code, func_ast.name) + + def build( + self, values: t.Mapping[str, t.Any], append_unknown: bool = True + ) -> t.Optional[t.Tuple[str, str]]: + """Assembles the relative url for that rule and the subdomain. + If building doesn't work for some reasons `None` is returned. + + :internal: + """ + try: + if append_unknown: + return self._build_unknown(**values) + else: + return self._build(**values) + except ValidationError: + return None + + def provides_defaults_for(self, rule: "Rule") -> bool: + """Check if this rule has defaults for a given rule. + + :internal: + """ + return bool( + not self.build_only + and self.defaults + and self.endpoint == rule.endpoint + and self != rule + and self.arguments == rule.arguments + ) + + def suitable_for( + self, values: t.Mapping[str, t.Any], method: t.Optional[str] = None + ) -> bool: + """Check if the dict of values has enough data for url generation. + + :internal: + """ + # if a method was given explicitly and that method is not supported + # by this rule, this rule is not suitable. + if ( + method is not None + and self.methods is not None + and method not in self.methods + ): + return False + + defaults = self.defaults or () + + # all arguments required must be either in the defaults dict or + # the value dictionary otherwise it's not suitable + for key in self.arguments: + if key not in defaults and key not in values: + return False + + # in case defaults are given we ensure that either the value was + # skipped or the value is the same as the default value. + if defaults: + for key, value in defaults.items(): + if key in values and value != values[key]: + return False + + return True + + def match_compare_key( + self, + ) -> t.Tuple[bool, int, t.Iterable[t.Tuple[int, int]], int, t.Iterable[int]]: + """The match compare key for sorting. + + Current implementation: + + 1. rules without any arguments come first for performance + reasons only as we expect them to match faster and some + common ones usually don't have any arguments (index pages etc.) + 2. rules with more static parts come first so the second argument + is the negative length of the number of the static weights. + 3. we order by static weights, which is a combination of index + and length + 4. The more complex rules come first so the next argument is the + negative length of the number of argument weights. + 5. lastly we order by the actual argument weights. + + :internal: + """ + return ( + bool(self.arguments), + -len(self._static_weights), + self._static_weights, + -len(self._argument_weights), + self._argument_weights, + ) + + def build_compare_key(self) -> t.Tuple[int, int, int]: + """The build compare key for sorting. + + :internal: + """ + return (1 if self.alias else 0, -len(self.arguments), -len(self.defaults or ())) + + def __eq__(self, other: object) -> bool: + return isinstance(other, type(self)) and self._trace == other._trace + + __hash__ = None # type: ignore + + def __str__(self) -> str: + return self.rule + + def __repr__(self) -> str: + if self.map is None: + return f"<{type(self).__name__} (unbound)>" + parts = [] + for is_dynamic, data in self._trace: + if is_dynamic: + parts.append(f"<{data}>") + else: + parts.append(data) + parts = "".join(parts).lstrip("|") + methods = f" ({', '.join(self.methods)})" if self.methods is not None else "" + return f"<{type(self).__name__} {parts!r}{methods} -> {self.endpoint}>" + + +class BaseConverter: + """Base class for all converters.""" + + regex = "[^/]+" + weight = 100 + + def __init__(self, map: "Map", *args: t.Any, **kwargs: t.Any) -> None: + self.map = map + + def to_python(self, value: str) -> t.Any: + return value + + def to_url(self, value: t.Any) -> str: + if isinstance(value, (bytes, bytearray)): + return _fast_url_quote(value) + return _fast_url_quote(str(value).encode(self.map.charset)) + + +class UnicodeConverter(BaseConverter): + """This converter is the default converter and accepts any string but + only one path segment. Thus the string can not include a slash. + + This is the default validator. + + Example:: + + Rule('/pages/'), + Rule('/') + + :param map: the :class:`Map`. + :param minlength: the minimum length of the string. Must be greater + or equal 1. + :param maxlength: the maximum length of the string. + :param length: the exact length of the string. + """ + + def __init__( + self, + map: "Map", + minlength: int = 1, + maxlength: t.Optional[int] = None, + length: t.Optional[int] = None, + ) -> None: + super().__init__(map) + if length is not None: + length_regex = f"{{{int(length)}}}" + else: + if maxlength is None: + maxlength_value = "" + else: + maxlength_value = str(int(maxlength)) + length_regex = f"{{{int(minlength)},{maxlength_value}}}" + self.regex = f"[^/]{length_regex}" + + +class AnyConverter(BaseConverter): + """Matches one of the items provided. Items can either be Python + identifiers or strings:: + + Rule('/') + + :param map: the :class:`Map`. + :param items: this function accepts the possible items as positional + arguments. + """ + + def __init__(self, map: "Map", *items: str) -> None: + super().__init__(map) + self.regex = f"(?:{'|'.join([re.escape(x) for x in items])})" + + +class PathConverter(BaseConverter): + """Like the default :class:`UnicodeConverter`, but it also matches + slashes. This is useful for wikis and similar applications:: + + Rule('/') + Rule('//edit') + + :param map: the :class:`Map`. + """ + + regex = "[^/].*?" + weight = 200 + + +class NumberConverter(BaseConverter): + """Baseclass for `IntegerConverter` and `FloatConverter`. + + :internal: + """ + + weight = 50 + num_convert: t.Callable = int + + def __init__( + self, + map: "Map", + fixed_digits: int = 0, + min: t.Optional[int] = None, + max: t.Optional[int] = None, + signed: bool = False, + ) -> None: + if signed: + self.regex = self.signed_regex + super().__init__(map) + self.fixed_digits = fixed_digits + self.min = min + self.max = max + self.signed = signed + + def to_python(self, value: str) -> t.Any: + if self.fixed_digits and len(value) != self.fixed_digits: + raise ValidationError() + value = self.num_convert(value) + if (self.min is not None and value < self.min) or ( + self.max is not None and value > self.max + ): + raise ValidationError() + return value + + def to_url(self, value: t.Any) -> str: + value = str(self.num_convert(value)) + if self.fixed_digits: + value = value.zfill(self.fixed_digits) + return value + + @property + def signed_regex(self) -> str: + return f"-?{self.regex}" + + +class IntegerConverter(NumberConverter): + """This converter only accepts integer values:: + + Rule("/page/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/page/") + + :param map: The :class:`Map`. + :param fixed_digits: The number of fixed digits in the URL. If you + set this to ``4`` for example, the rule will only match if the + URL looks like ``/0001/``. The default is variable length. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+" + + +class FloatConverter(NumberConverter): + """This converter only accepts floating point values:: + + Rule("/probability/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/offset/") + + :param map: The :class:`Map`. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+\.\d+" + num_convert = float + + def __init__( + self, + map: "Map", + min: t.Optional[float] = None, + max: t.Optional[float] = None, + signed: bool = False, + ) -> None: + super().__init__(map, min=min, max=max, signed=signed) # type: ignore + + +class UUIDConverter(BaseConverter): + """This converter only accepts UUID strings:: + + Rule('/object/') + + .. versionadded:: 0.10 + + :param map: the :class:`Map`. + """ + + regex = ( + r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-" + r"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + ) + + def to_python(self, value: str) -> uuid.UUID: + return uuid.UUID(value) + + def to_url(self, value: uuid.UUID) -> str: + return str(value) + + +#: the default converter mapping for the map. +DEFAULT_CONVERTERS: t.Mapping[str, t.Type[BaseConverter]] = { + "default": UnicodeConverter, + "string": UnicodeConverter, + "any": AnyConverter, + "path": PathConverter, + "int": IntegerConverter, + "float": FloatConverter, + "uuid": UUIDConverter, +} + + +class Map: + """The map class stores all the URL rules and some configuration + parameters. Some of the configuration values are only stored on the + `Map` instance since those affect all rules, others are just defaults + and can be overridden for each rule. Note that you have to specify all + arguments besides the `rules` as keyword arguments! + + :param rules: sequence of url rules for this map. + :param default_subdomain: The default subdomain for rules without a + subdomain defined. + :param charset: charset of the url. defaults to ``"utf-8"`` + :param strict_slashes: If a rule ends with a slash but the matched + URL does not, redirect to the URL with a trailing slash. + :param merge_slashes: Merge consecutive slashes when matching or + building URLs. Matches will redirect to the normalized URL. + Slashes in variable parts are not merged. + :param redirect_defaults: This will redirect to the default rule if it + wasn't visited that way. This helps creating + unique URLs. + :param converters: A dict of converters that adds additional converters + to the list of converters. If you redefine one + converter this will override the original one. + :param sort_parameters: If set to `True` the url parameters are sorted. + See `url_encode` for more details. + :param sort_key: The sort key function for `url_encode`. + :param encoding_errors: the error method to use for decoding + :param host_matching: if set to `True` it enables the host matching + feature and disables the subdomain one. If + enabled the `host` parameter to rules is used + instead of the `subdomain` one. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules + will match. + + .. versionchanged:: 1.0 + Added ``merge_slashes``. + + .. versionchanged:: 0.7 + Added ``encoding_errors`` and ``host_matching``. + + .. versionchanged:: 0.5 + Added ``sort_parameters`` and ``sort_key``. + """ + + #: A dict of default converters to be used. + default_converters = ImmutableDict(DEFAULT_CONVERTERS) + + #: The type of lock to use when updating. + #: + #: .. versionadded:: 1.0 + lock_class = Lock + + def __init__( + self, + rules: t.Optional[t.Iterable[RuleFactory]] = None, + default_subdomain: str = "", + charset: str = "utf-8", + strict_slashes: bool = True, + merge_slashes: bool = True, + redirect_defaults: bool = True, + converters: t.Optional[t.Mapping[str, t.Type[BaseConverter]]] = None, + sort_parameters: bool = False, + sort_key: t.Optional[t.Callable[[t.Any], t.Any]] = None, + encoding_errors: str = "replace", + host_matching: bool = False, + ) -> None: + self._rules: t.List[Rule] = [] + self._rules_by_endpoint: t.Dict[str, t.List[Rule]] = {} + self._remap = True + self._remap_lock = self.lock_class() + + self.default_subdomain = default_subdomain + self.charset = charset + self.encoding_errors = encoding_errors + self.strict_slashes = strict_slashes + self.merge_slashes = merge_slashes + self.redirect_defaults = redirect_defaults + self.host_matching = host_matching + + self.converters = self.default_converters.copy() + if converters: + self.converters.update(converters) + + self.sort_parameters = sort_parameters + self.sort_key = sort_key + + for rulefactory in rules or (): + self.add(rulefactory) + + def is_endpoint_expecting(self, endpoint: str, *arguments: str) -> bool: + """Iterate over all rules and check if the endpoint expects + the arguments provided. This is for example useful if you have + some URLs that expect a language code and others that do not and + you want to wrap the builder a bit so that the current language + code is automatically added if not provided but endpoints expect + it. + + :param endpoint: the endpoint to check. + :param arguments: this function accepts one or more arguments + as positional arguments. Each one of them is + checked. + """ + self.update() + arguments = set(arguments) + for rule in self._rules_by_endpoint[endpoint]: + if arguments.issubset(rule.arguments): + return True + return False + + def iter_rules(self, endpoint: t.Optional[str] = None) -> t.Iterator[Rule]: + """Iterate over all rules or the rules of an endpoint. + + :param endpoint: if provided only the rules for that endpoint + are returned. + :return: an iterator + """ + self.update() + if endpoint is not None: + return iter(self._rules_by_endpoint[endpoint]) + return iter(self._rules) + + def add(self, rulefactory: RuleFactory) -> None: + """Add a new rule or factory to the map and bind it. Requires that the + rule is not bound to another map. + + :param rulefactory: a :class:`Rule` or :class:`RuleFactory` + """ + for rule in rulefactory.get_rules(self): + rule.bind(self) + self._rules.append(rule) + self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule) + self._remap = True + + def bind( + self, + server_name: str, + script_name: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + url_scheme: str = "http", + default_method: str = "GET", + path_info: t.Optional[str] = None, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + ) -> "MapAdapter": + """Return a new :class:`MapAdapter` with the details specified to the + call. Note that `script_name` will default to ``'/'`` if not further + specified or `None`. The `server_name` at least is a requirement + because the HTTP RFC requires absolute URLs for redirects and so all + redirect exceptions raised by Werkzeug will contain the full canonical + URL. + + If no path_info is passed to :meth:`match` it will use the default path + info passed to bind. While this doesn't really make sense for + manual bind calls, it's useful if you bind a map to a WSGI + environment which already contains the path info. + + `subdomain` will default to the `default_subdomain` for this map if + no defined. If there is no `default_subdomain` you cannot use the + subdomain feature. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules + will match. + + .. versionchanged:: 0.15 + ``path_info`` defaults to ``'/'`` if ``None``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionchanged:: 0.7 + Added ``query_args``. + """ + server_name = server_name.lower() + if self.host_matching: + if subdomain is not None: + raise RuntimeError("host matching enabled and a subdomain was provided") + elif subdomain is None: + subdomain = self.default_subdomain + if script_name is None: + script_name = "/" + if path_info is None: + path_info = "/" + + try: + server_name = _encode_idna(server_name) # type: ignore + except UnicodeError as e: + raise BadHost() from e + + return MapAdapter( + self, + server_name, + script_name, + subdomain, + url_scheme, + path_info, + default_method, + query_args, + ) + + def bind_to_environ( + self, + environ: t.Union["WSGIEnvironment", "Request"], + server_name: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + ) -> "MapAdapter": + """Like :meth:`bind` but you can pass it an WSGI environment and it + will fetch the information from that dictionary. Note that because of + limitations in the protocol there is no way to get the current + subdomain and real `server_name` from the environment. If you don't + provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or + `HTTP_HOST` if provided) as used `server_name` with disabled subdomain + feature. + + If `subdomain` is `None` but an environment and a server name is + provided it will calculate the current subdomain automatically. + Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` + in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated + subdomain will be ``'staging.dev'``. + + If the object passed as environ has an environ attribute, the value of + this attribute is used instead. This allows you to pass request + objects. Additionally `PATH_INFO` added as a default of the + :class:`MapAdapter` so that you don't have to pass the path info to + the match method. + + .. versionchanged:: 1.0.0 + If the passed server name specifies port 443, it will match + if the incoming scheme is ``https`` without a port. + + .. versionchanged:: 1.0.0 + A warning is shown when the passed server name does not + match the incoming WSGI server name. + + .. versionchanged:: 0.8 + This will no longer raise a ValueError when an unexpected server + name was passed. + + .. versionchanged:: 0.5 + previously this method accepted a bogus `calculate_subdomain` + parameter that did not have any effect. It was removed because + of that. + + :param environ: a WSGI environment. + :param server_name: an optional server name hint (see above). + :param subdomain: optionally the current subdomain (see above). + """ + env = _get_environ(environ) + wsgi_server_name = get_host(env).lower() + scheme = env["wsgi.url_scheme"] + upgrade = any( + v.strip() == "upgrade" + for v in env.get("HTTP_CONNECTION", "").lower().split(",") + ) + + if upgrade and env.get("HTTP_UPGRADE", "").lower() == "websocket": + scheme = "wss" if scheme == "https" else "ws" + + if server_name is None: + server_name = wsgi_server_name + else: + server_name = server_name.lower() + + # strip standard port to match get_host() + if scheme in {"http", "ws"} and server_name.endswith(":80"): + server_name = server_name[:-3] + elif scheme in {"https", "wss"} and server_name.endswith(":443"): + server_name = server_name[:-4] + + if subdomain is None and not self.host_matching: + cur_server_name = wsgi_server_name.split(".") + real_server_name = server_name.split(".") + offset = -len(real_server_name) + + if cur_server_name[offset:] != real_server_name: + # This can happen even with valid configs if the server was + # accessed directly by IP address under some situations. + # Instead of raising an exception like in Werkzeug 0.7 or + # earlier we go by an invalid subdomain which will result + # in a 404 error on matching. + warnings.warn( + f"Current server name {wsgi_server_name!r} doesn't match configured" + f" server name {server_name!r}", + stacklevel=2, + ) + subdomain = "" + else: + subdomain = ".".join(filter(None, cur_server_name[:offset])) + + def _get_wsgi_string(name: str) -> t.Optional[str]: + val = env.get(name) + if val is not None: + return _wsgi_decoding_dance(val, self.charset) + return None + + script_name = _get_wsgi_string("SCRIPT_NAME") + path_info = _get_wsgi_string("PATH_INFO") + query_args = _get_wsgi_string("QUERY_STRING") + return Map.bind( + self, + server_name, + script_name, + subdomain, + scheme, + env["REQUEST_METHOD"], + path_info, + query_args=query_args, + ) + + def update(self) -> None: + """Called before matching and building to keep the compiled rules + in the correct order after things changed. + """ + if not self._remap: + return + + with self._remap_lock: + if not self._remap: + return + + self._rules.sort(key=lambda x: x.match_compare_key()) + for rules in self._rules_by_endpoint.values(): + rules.sort(key=lambda x: x.build_compare_key()) + self._remap = False + + def __repr__(self) -> str: + rules = self.iter_rules() + return f"{type(self).__name__}({pformat(list(rules))})" + + +class MapAdapter: + + """Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does + the URL matching and building based on runtime information. + """ + + def __init__( + self, + map: Map, + server_name: str, + script_name: str, + subdomain: t.Optional[str], + url_scheme: str, + path_info: str, + default_method: str, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + ): + self.map = map + self.server_name = _to_str(server_name) + script_name = _to_str(script_name) + if not script_name.endswith("/"): + script_name += "/" + self.script_name = script_name + self.subdomain = _to_str(subdomain) + self.url_scheme = _to_str(url_scheme) + self.path_info = _to_str(path_info) + self.default_method = _to_str(default_method) + self.query_args = query_args + self.websocket = self.url_scheme in {"ws", "wss"} + + def dispatch( + self, + view_func: t.Callable[[str, t.Mapping[str, t.Any]], "WSGIApplication"], + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + catch_http_exceptions: bool = False, + ) -> "WSGIApplication": + """Does the complete dispatching process. `view_func` is called with + the endpoint and a dict with the values for the view. It should + look up the view function, call it, and return a response object + or WSGI application. http exceptions are not caught by default + so that applications can display nicer error messages by just + catching them by hand. If you want to stick with the default + error messages you can pass it ``catch_http_exceptions=True`` and + it will catch the http exceptions. + + Here a small example for the dispatch usage:: + + from werkzeug.wrappers import Request, Response + from werkzeug.wsgi import responder + from werkzeug.routing import Map, Rule + + def on_index(request): + return Response('Hello from the index') + + url_map = Map([Rule('/', endpoint='index')]) + views = {'index': on_index} + + @responder + def application(environ, start_response): + request = Request(environ) + urls = url_map.bind_to_environ(environ) + return urls.dispatch(lambda e, v: views[e](request, **v), + catch_http_exceptions=True) + + Keep in mind that this method might return exception objects, too, so + use :class:`Response.force_type` to get a response object. + + :param view_func: a function that is called with the endpoint as + first argument and the value dict as second. Has + to dispatch to the actual view function with this + information. (see above) + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param catch_http_exceptions: set to `True` to catch any of the + werkzeug :class:`HTTPException`\\s. + """ + try: + try: + endpoint, args = self.match(path_info, method) + except RequestRedirect as e: + return e + return view_func(endpoint, args) + except HTTPException as e: + if catch_http_exceptions: + return e + raise + + @typing.overload + def match( # type: ignore + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: "te.Literal[False]" = False, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[str, t.Mapping[str, t.Any]]: + ... + + @typing.overload + def match( + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: "te.Literal[True]" = True, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[Rule, t.Mapping[str, t.Any]]: + ... + + def match( + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: bool = False, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[t.Union[str, Rule], t.Mapping[str, t.Any]]: + """The usage is simple: you just pass the match method the current + path info as well as the method (which defaults to `GET`). The + following things can then happen: + + - you receive a `NotFound` exception that indicates that no URL is + matching. A `NotFound` exception is also a WSGI application you + can call to get a default page not found page (happens to be the + same object as `werkzeug.exceptions.NotFound`) + + - you receive a `MethodNotAllowed` exception that indicates that there + is a match for this URL but not for the current request method. + This is useful for RESTful applications. + + - you receive a `RequestRedirect` exception with a `new_url` + attribute. This exception is used to notify you about a request + Werkzeug requests from your WSGI application. This is for example the + case if you request ``/foo`` although the correct URL is ``/foo/`` + You can use the `RequestRedirect` instance as response-like object + similar to all other subclasses of `HTTPException`. + + - you receive a ``WebsocketMismatch`` exception if the only + match is a WebSocket rule but the bind is an HTTP request, or + if the match is an HTTP rule but the bind is a WebSocket + request. + + - you get a tuple in the form ``(endpoint, arguments)`` if there is + a match (unless `return_rule` is True, in which case you get a tuple + in the form ``(rule, arguments)``) + + If the path info is not passed to the match method the default path + info of the map is used (defaults to the root URL if not defined + explicitly). + + All of the exceptions raised are subclasses of `HTTPException` so they + can be used as WSGI responses. They will all render generic error or + redirect pages. + + Here is a small example for matching: + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.match("/", "GET") + ('index', {}) + >>> urls.match("/downloads/42") + ('downloads/show', {'id': 42}) + + And here is what happens on redirect and missing URLs: + + >>> urls.match("/downloads") + Traceback (most recent call last): + ... + RequestRedirect: http://example.com/downloads/ + >>> urls.match("/missing") + Traceback (most recent call last): + ... + NotFound: 404 Not Found + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param return_rule: return the rule that matched instead of just the + endpoint (defaults to `False`). + :param query_args: optional query arguments that are used for + automatic redirects as string or dictionary. It's + currently not possible to use the query arguments + for URL matching. + :param websocket: Match WebSocket instead of HTTP requests. A + websocket request has a ``ws`` or ``wss`` + :attr:`url_scheme`. This overrides that detection. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionadded:: 0.7 + Added ``query_args``. + + .. versionadded:: 0.6 + Added ``return_rule``. + """ + self.map.update() + if path_info is None: + path_info = self.path_info + else: + path_info = _to_str(path_info, self.map.charset) + if query_args is None: + query_args = self.query_args or {} + method = (method or self.default_method).upper() + + if websocket is None: + websocket = self.websocket + + require_redirect = False + + domain_part = self.server_name if self.map.host_matching else self.subdomain + path_part = f"/{path_info.lstrip('/')}" if path_info else "" + path = f"{domain_part}|{path_part}" + + have_match_for = set() + websocket_mismatch = False + + for rule in self.map._rules: + try: + rv = rule.match(path, method) + except RequestPath as e: + raise RequestRedirect( + self.make_redirect_url( + url_quote(e.path_info, self.map.charset, safe="/:|+"), + query_args, + ) + ) from None + except RequestAliasRedirect as e: + raise RequestRedirect( + self.make_alias_redirect_url( + path, rule.endpoint, e.matched_values, method, query_args + ) + ) from None + if rv is None: + continue + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + continue + + if rule.websocket != websocket: + websocket_mismatch = True + continue + + if self.map.redirect_defaults: + redirect_url = self.get_default_redirect(rule, method, rv, query_args) + if redirect_url is not None: + raise RequestRedirect(redirect_url) + + if rule.redirect_to is not None: + if isinstance(rule.redirect_to, str): + + def _handle_match(match: t.Match[str]) -> str: + value = rv[match.group(1)] # type: ignore + return rule._converters[match.group(1)].to_url(value) + + redirect_url = _simple_rule_re.sub(_handle_match, rule.redirect_to) + else: + redirect_url = rule.redirect_to(self, **rv) + + if self.subdomain: + netloc = f"{self.subdomain}.{self.server_name}" + else: + netloc = self.server_name + + raise RequestRedirect( + url_join( + f"{self.url_scheme or 'http'}://{netloc}{self.script_name}", + redirect_url, + ) + ) + + if require_redirect: + raise RequestRedirect( + self.make_redirect_url( + url_quote(path_info, self.map.charset, safe="/:|+"), query_args + ) + ) + + if return_rule: + return rule, rv + else: + return rule.endpoint, rv + + if have_match_for: + raise MethodNotAllowed(valid_methods=list(have_match_for)) + + if websocket_mismatch: + raise WebsocketMismatch() + + raise NotFound() + + def test( + self, path_info: t.Optional[str] = None, method: t.Optional[str] = None + ) -> bool: + """Test if a rule would match. Works like `match` but returns `True` + if the URL matches, or `False` if it does not exist. + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + """ + try: + self.match(path_info, method) + except RequestRedirect: + pass + except HTTPException: + return False + return True + + def allowed_methods(self, path_info: t.Optional[str] = None) -> t.Iterable[str]: + """Returns the valid methods that match for a given path. + + .. versionadded:: 0.7 + """ + try: + self.match(path_info, method="--") + except MethodNotAllowed as e: + return e.valid_methods # type: ignore + except HTTPException: + pass + return [] + + def get_host(self, domain_part: t.Optional[str]) -> str: + """Figures out the full host name for the given domain part. The + domain part is a subdomain in case host matching is disabled or + a full host name. + """ + if self.map.host_matching: + if domain_part is None: + return self.server_name + return _to_str(domain_part, "ascii") + subdomain = domain_part + if subdomain is None: + subdomain = self.subdomain + else: + subdomain = _to_str(subdomain, "ascii") + + if subdomain: + return f"{subdomain}.{self.server_name}" + else: + return self.server_name + + def get_default_redirect( + self, + rule: Rule, + method: str, + values: t.MutableMapping[str, t.Any], + query_args: t.Union[t.Mapping[str, t.Any], str], + ) -> t.Optional[str]: + """A helper that returns the URL to redirect to if it finds one. + This is used for default redirecting only. + + :internal: + """ + assert self.map.redirect_defaults + for r in self.map._rules_by_endpoint[rule.endpoint]: + # every rule that comes after this one, including ourself + # has a lower priority for the defaults. We order the ones + # with the highest priority up for building. + if r is rule: + break + if r.provides_defaults_for(rule) and r.suitable_for(values, method): + values.update(r.defaults) # type: ignore + domain_part, path = r.build(values) # type: ignore + return self.make_redirect_url(path, query_args, domain_part=domain_part) + return None + + def encode_query_args(self, query_args: t.Union[t.Mapping[str, t.Any], str]) -> str: + if not isinstance(query_args, str): + return url_encode(query_args, self.map.charset) + return query_args + + def make_redirect_url( + self, + path_info: str, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + domain_part: t.Optional[str] = None, + ) -> str: + """Creates a redirect URL. + + :internal: + """ + if query_args: + suffix = f"?{self.encode_query_args(query_args)}" + else: + suffix = "" + + scheme = self.url_scheme or "http" + host = self.get_host(domain_part) + path = posixpath.join(self.script_name.strip("/"), path_info.lstrip("/")) + return f"{scheme}://{host}/{path}{suffix}" + + def make_alias_redirect_url( + self, + path: str, + endpoint: str, + values: t.Mapping[str, t.Any], + method: str, + query_args: t.Union[t.Mapping[str, t.Any], str], + ) -> str: + """Internally called to make an alias redirect URL.""" + url = self.build( + endpoint, values, method, append_unknown=False, force_external=True + ) + if query_args: + url += f"?{self.encode_query_args(query_args)}" + assert url != path, "detected invalid alias setting. No canonical URL found" + return url + + def _partial_build( + self, + endpoint: str, + values: t.Mapping[str, t.Any], + method: t.Optional[str], + append_unknown: bool, + ) -> t.Optional[t.Tuple[str, str, bool]]: + """Helper for :meth:`build`. Returns subdomain and path for the + rule that accepts this endpoint, values and method. + + :internal: + """ + # in case the method is none, try with the default method first + if method is None: + rv = self._partial_build( + endpoint, values, self.default_method, append_unknown + ) + if rv is not None: + return rv + + # Default method did not match or a specific method is passed. + # Check all for first match with matching host. If no matching + # host is found, go with first result. + first_match = None + + for rule in self.map._rules_by_endpoint.get(endpoint, ()): + if rule.suitable_for(values, method): + build_rv = rule.build(values, append_unknown) + + if build_rv is not None: + rv = (build_rv[0], build_rv[1], rule.websocket) + if self.map.host_matching: + if rv[0] == self.server_name: + return rv + elif first_match is None: + first_match = rv + else: + return rv + + return first_match + + def build( + self, + endpoint: str, + values: t.Optional[t.Mapping[str, t.Any]] = None, + method: t.Optional[str] = None, + force_external: bool = False, + append_unknown: bool = True, + url_scheme: t.Optional[str] = None, + ) -> str: + """Building URLs works pretty much the other way round. Instead of + `match` you call `build` and pass it the endpoint and a dict of + arguments for the placeholders. + + The `build` function also accepts an argument called `force_external` + which, if you set it to `True` will force external URLs. Per default + external URLs (include the server name) will only be used if the + target URL is on a different subdomain. + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.build("index", {}) + '/' + >>> urls.build("downloads/show", {'id': 42}) + '/downloads/42' + >>> urls.build("downloads/show", {'id': 42}, force_external=True) + 'http://example.com/downloads/42' + + Because URLs cannot contain non ASCII data you will always get + bytes back. Non ASCII characters are urlencoded with the + charset defined on the map instance. + + Additional values are converted to strings and appended to the URL as + URL querystring parameters: + + >>> urls.build("index", {'q': 'My Searchstring'}) + '/?q=My+Searchstring' + + When processing those additional values, lists are furthermore + interpreted as multiple values (as per + :py:class:`werkzeug.datastructures.MultiDict`): + + >>> urls.build("index", {'q': ['a', 'b', 'c']}) + '/?q=a&q=b&q=c' + + Passing a ``MultiDict`` will also add multiple values: + + >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 'b')))) + '/?p=z&q=a&q=b' + + If a rule does not exist when building a `BuildError` exception is + raised. + + The build method accepts an argument called `method` which allows you + to specify the method you want to have an URL built for if you have + different methods for the same endpoint specified. + + :param endpoint: the endpoint of the URL to build. + :param values: the values for the URL to build. Unhandled values are + appended to the URL as query parameters. + :param method: the HTTP method for the rule if there are different + URLs for different methods on the same endpoint. + :param force_external: enforce full canonical external URLs. If the URL + scheme is not provided, this will generate + a protocol-relative URL. + :param append_unknown: unknown parameters are appended to the generated + URL as query string argument. Disable this + if you want the builder to ignore those. + :param url_scheme: Scheme to use in place of the bound + :attr:`url_scheme`. + + .. versionchanged:: 2.0 + Added the ``url_scheme`` parameter. + + .. versionadded:: 0.6 + Added the ``append_unknown`` parameter. + """ + self.map.update() + + if values: + if isinstance(values, MultiDict): + values = { + k: (v[0] if len(v) == 1 else v) + for k, v in dict.items(values) + if len(v) != 0 + } + else: # plain dict + values = {k: v for k, v in values.items() if v is not None} + else: + values = {} + + rv = self._partial_build(endpoint, values, method, append_unknown) + if rv is None: + raise BuildError(endpoint, values, method, self) + + domain_part, path, websocket = rv + host = self.get_host(domain_part) + + if url_scheme is None: + url_scheme = self.url_scheme + + # Always build WebSocket routes with the scheme (browsers + # require full URLs). If bound to a WebSocket, ensure that HTTP + # routes are built with an HTTP scheme. + secure = url_scheme in {"https", "wss"} + + if websocket: + force_external = True + url_scheme = "wss" if secure else "ws" + elif url_scheme: + url_scheme = "https" if secure else "http" + + # shortcut this. + if not force_external and ( + (self.map.host_matching and host == self.server_name) + or (not self.map.host_matching and domain_part == self.subdomain) + ): + return f"{self.script_name.rstrip('/')}/{path.lstrip('/')}" + + scheme = f"{url_scheme}:" if url_scheme else "" + return f"{scheme}//{host}{self.script_name[:-1]}/{path.lstrip('/')}" diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/sansio/__init__.py b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/sansio/multipart.py b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/multipart.py new file mode 100644 index 0000000..2d54422 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/multipart.py @@ -0,0 +1,260 @@ +import re +from dataclasses import dataclass +from enum import auto +from enum import Enum +from typing import cast +from typing import List +from typing import Optional +from typing import Tuple + +from .._internal import _to_bytes +from .._internal import _to_str +from ..datastructures import Headers +from ..exceptions import RequestEntityTooLarge +from ..http import parse_options_header + + +class Event: + pass + + +@dataclass(frozen=True) +class Preamble(Event): + data: bytes + + +@dataclass(frozen=True) +class Field(Event): + name: str + headers: Headers + + +@dataclass(frozen=True) +class File(Event): + name: str + filename: str + headers: Headers + + +@dataclass(frozen=True) +class Data(Event): + data: bytes + more_data: bool + + +@dataclass(frozen=True) +class Epilogue(Event): + data: bytes + + +class NeedData(Event): + pass + + +NEED_DATA = NeedData() + + +class State(Enum): + PREAMBLE = auto() + PART = auto() + DATA = auto() + EPILOGUE = auto() + COMPLETE = auto() + + +# Multipart line breaks MUST be CRLF (\r\n) by RFC-7578, except that +# many implementations break this and either use CR or LF alone. +LINE_BREAK = b"(?:\r\n|\n|\r)" +BLANK_LINE_RE = re.compile(b"(?:\r\n\r\n|\r\r|\n\n)", re.MULTILINE) +LINE_BREAK_RE = re.compile(LINE_BREAK, re.MULTILINE) +# Header values can be continued via a space or tab after the linebreak, as +# per RFC2231 +HEADER_CONTINUATION_RE = re.compile(b"%s[ \t]" % LINE_BREAK, re.MULTILINE) + + +class MultipartDecoder: + """Decodes a multipart message as bytes into Python events. + + The part data is returned as available to allow the caller to save + the data from memory to disk, if desired. + """ + + def __init__( + self, + boundary: bytes, + max_form_memory_size: Optional[int] = None, + ) -> None: + self.buffer = bytearray() + self.complete = False + self.max_form_memory_size = max_form_memory_size + self.state = State.PREAMBLE + self.boundary = boundary + + # Note in the below \h i.e. horizontal whitespace is used + # as [^\S\n\r] as \h isn't supported in python. + + # The preamble must end with a boundary where the boundary is + # prefixed by a line break, RFC2046. Except that many + # implementations including Werkzeug's tests omit the line + # break prefix. In addition the first boundary could be the + # epilogue boundary (for empty form-data) hence the matching + # group to understand if it is an epilogue boundary. + self.preamble_re = re.compile( + rb"%s?--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + # A boundary must include a line break prefix and suffix, and + # may include trailing whitespace. In addition the boundary + # could be the epilogue boundary hence the matching group to + # understand if it is an epilogue boundary. + self.boundary_re = re.compile( + rb"%s--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + + def last_newline(self) -> int: + try: + last_nl = self.buffer.rindex(b"\n") + except ValueError: + last_nl = len(self.buffer) + try: + last_cr = self.buffer.rindex(b"\r") + except ValueError: + last_cr = len(self.buffer) + + return min(last_nl, last_cr) + + def receive_data(self, data: Optional[bytes]) -> None: + if data is None: + self.complete = True + elif ( + self.max_form_memory_size is not None + and len(self.buffer) + len(data) > self.max_form_memory_size + ): + raise RequestEntityTooLarge() + else: + self.buffer.extend(data) + + def next_event(self) -> Event: + event: Event = NEED_DATA + + if self.state == State.PREAMBLE: + match = self.preamble_re.search(self.buffer) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data = bytes(self.buffer[: match.start()]) + del self.buffer[: match.end()] + event = Preamble(data=data) + + elif self.state == State.PART: + match = BLANK_LINE_RE.search(self.buffer) + if match is not None: + headers = self._parse_headers(self.buffer[: match.start()]) + del self.buffer[: match.end()] + + if "content-disposition" not in headers: + raise ValueError("Missing Content-Disposition header") + + disposition, extra = parse_options_header( + headers["content-disposition"] + ) + name = cast(str, extra.get("name")) + filename = extra.get("filename") + if filename is not None: + event = File( + filename=filename, + headers=headers, + name=name, + ) + else: + event = Field( + headers=headers, + name=name, + ) + self.state = State.DATA + + elif self.state == State.DATA: + if self.buffer.find(b"--" + self.boundary) == -1: + # No complete boundary in the buffer, but there may be + # a partial boundary at the end. As the boundary + # starts with either a nl or cr find the earliest and + # return up to that as data. + data_length = del_index = self.last_newline() + more_data = True + else: + match = self.boundary_re.search(self.buffer) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data_length = match.start() + del_index = match.end() + else: + data_length = del_index = self.last_newline() + more_data = match is None + + data = bytes(self.buffer[:data_length]) + del self.buffer[:del_index] + if data or not more_data: + event = Data(data=data, more_data=more_data) + + elif self.state == State.EPILOGUE and self.complete: + event = Epilogue(data=bytes(self.buffer)) + del self.buffer[:] + self.state = State.COMPLETE + + if self.complete and isinstance(event, NeedData): + raise ValueError(f"Invalid form-data cannot parse beyond {self.state}") + + return event + + def _parse_headers(self, data: bytes) -> Headers: + headers: List[Tuple[str, str]] = [] + # Merge the continued headers into one line + data = HEADER_CONTINUATION_RE.sub(b" ", data) + # Now there is one header per line + for line in data.splitlines(): + if line.strip() != b"": + name, value = _to_str(line).strip().split(":", 1) + headers.append((name.strip(), value.strip())) + return Headers(headers) + + +class MultipartEncoder: + def __init__(self, boundary: bytes) -> None: + self.boundary = boundary + self.state = State.PREAMBLE + + def send_event(self, event: Event) -> bytes: + if isinstance(event, Preamble) and self.state == State.PREAMBLE: + self.state = State.PART + return event.data + elif isinstance(event, (Field, File)) and self.state in { + State.PREAMBLE, + State.PART, + State.DATA, + }: + self.state = State.DATA + data = b"\r\n--" + self.boundary + b"\r\n" + data += b'Content-Disposition: form-data; name="%s"' % _to_bytes(event.name) + if isinstance(event, File): + data += b'; filename="%s"' % _to_bytes(event.filename) + data += b"\r\n" + for name, value in cast(Field, event).headers: + if name.lower() != "content-disposition": + data += _to_bytes(f"{name}: {value}\r\n") + data += b"\r\n" + return data + elif isinstance(event, Data) and self.state == State.DATA: + return event.data + elif isinstance(event, Epilogue): + self.state = State.COMPLETE + return b"\r\n--" + self.boundary + b"--\r\n" + event.data + else: + raise ValueError(f"Cannot generate {event} in state: {self.state}") diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/sansio/request.py b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/request.py new file mode 100644 index 0000000..3802403 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/request.py @@ -0,0 +1,547 @@ +import typing as t +from datetime import datetime + +from .._internal import _to_str +from ..datastructures import Accept +from ..datastructures import Authorization +from ..datastructures import CharsetAccept +from ..datastructures import ETags +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..datastructures import IfRange +from ..datastructures import ImmutableList +from ..datastructures import ImmutableMultiDict +from ..datastructures import LanguageAccept +from ..datastructures import MIMEAccept +from ..datastructures import MultiDict +from ..datastructures import Range +from ..datastructures import RequestCacheControl +from ..http import parse_accept_header +from ..http import parse_authorization_header +from ..http import parse_cache_control_header +from ..http import parse_cookie +from ..http import parse_date +from ..http import parse_etags +from ..http import parse_if_range_header +from ..http import parse_list_header +from ..http import parse_options_header +from ..http import parse_range_header +from ..http import parse_set_header +from ..urls import url_decode +from ..user_agent import UserAgent +from ..utils import cached_property +from ..utils import header_property +from .utils import get_current_url +from .utils import get_host + + +class Request: + """Represents the non-IO parts of a HTTP request, including the + method, URL info, and headers. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Request`. + + :param method: The method the request was made with, such as + ``GET``. + :param scheme: The URL scheme of the protocol the request used, such + as ``https`` or ``wss``. + :param server: The address of the server. ``(host, port)``, + ``(path, None)`` for unix sockets, or ``None`` if not known. + :param root_path: The prefix that the application is mounted under. + This is prepended to generated URLs, but is not part of route + matching. + :param path: The path part of the URL after ``root_path``. + :param query_string: The part of the URL after the "?". + :param headers: The headers received with the request. + :param remote_addr: The address of the client sending the request. + + .. versionadded:: 2.0 + """ + + #: The charset used to decode most data in the request. + charset = "utf-8" + + #: the error handling procedure for errors, defaults to 'replace' + encoding_errors = "replace" + + #: the class to use for `args` and `form`. The default is an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` which supports + #: multiple values per key. alternatively it makes sense to use an + #: :class:`~werkzeug.datastructures.ImmutableOrderedMultiDict` which + #: preserves order or a :class:`~werkzeug.datastructures.ImmutableDict` + #: which is the fastest but only remembers the last key. It is also + #: possible to use mutable structures, but this is not recommended. + #: + #: .. versionadded:: 0.6 + parameter_storage_class: t.Type[MultiDict] = ImmutableMultiDict + + #: The type to be used for dict values from the incoming WSGI + #: environment. (For example for :attr:`cookies`.) By default an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` is used. + #: + #: .. versionchanged:: 1.0.0 + #: Changed to ``ImmutableMultiDict`` to support multiple values. + #: + #: .. versionadded:: 0.6 + dict_storage_class: t.Type[MultiDict] = ImmutableMultiDict + + #: the type to be used for list values from the incoming WSGI environment. + #: By default an :class:`~werkzeug.datastructures.ImmutableList` is used + #: (for example for :attr:`access_list`). + #: + #: .. versionadded:: 0.6 + list_storage_class: t.Type[t.List] = ImmutableList + + user_agent_class: t.Type[UserAgent] = UserAgent + """The class used and returned by the :attr:`user_agent` property to + parse the header. Defaults to + :class:`~werkzeug.user_agent.UserAgent`, which does no parsing. An + extension can provide a subclass that uses a parser to provide other + data. + + .. versionadded:: 2.0 + """ + + #: Valid host names when handling requests. By default all hosts are + #: trusted, which means that whatever the client says the host is + #: will be accepted. + #: + #: Because ``Host`` and ``X-Forwarded-Host`` headers can be set to + #: any value by a malicious client, it is recommended to either set + #: this property or implement similar validation in the proxy (if + #: the application is being run behind one). + #: + #: .. versionadded:: 0.9 + trusted_hosts: t.Optional[t.List[str]] = None + + def __init__( + self, + method: str, + scheme: str, + server: t.Optional[t.Tuple[str, t.Optional[int]]], + root_path: str, + path: str, + query_string: bytes, + headers: Headers, + remote_addr: t.Optional[str], + ) -> None: + #: The method the request was made with, such as ``GET``. + self.method = method.upper() + #: The URL scheme of the protocol the request used, such as + #: ``https`` or ``wss``. + self.scheme = scheme + #: The address of the server. ``(host, port)``, ``(path, None)`` + #: for unix sockets, or ``None`` if not known. + self.server = server + #: The prefix that the application is mounted under, without a + #: trailing slash. :attr:`path` comes after this. + self.root_path = root_path.rstrip("/") + #: The path part of the URL after :attr:`root_path`. This is the + #: path used for routing within the application. + self.path = "/" + path.lstrip("/") + #: The part of the URL after the "?". This is the raw value, use + #: :attr:`args` for the parsed values. + self.query_string = query_string + #: The headers received with the request. + self.headers = headers + #: The address of the client sending the request. + self.remote_addr = remote_addr + + def __repr__(self) -> str: + try: + url = self.url + except Exception as e: + url = f"(invalid URL: {e})" + + return f"<{type(self).__name__} {url!r} [{self.method}]>" + + @property + def url_charset(self) -> str: + """The charset that is assumed for URLs. Defaults to the value + of :attr:`charset`. + + .. versionadded:: 0.6 + """ + return self.charset + + @cached_property + def args(self) -> "MultiDict[str, str]": + """The parsed URL parameters (the part in the URL after the question + mark). + + By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + """ + return url_decode( + self.query_string, + self.url_charset, + errors=self.encoding_errors, + cls=self.parameter_storage_class, + ) + + @cached_property + def access_route(self) -> t.List[str]: + """If a forwarded header exists this is a list of all ip addresses + from the client ip to the last proxy server. + """ + if "X-Forwarded-For" in self.headers: + return self.list_storage_class( + parse_list_header(self.headers["X-Forwarded-For"]) + ) + elif self.remote_addr is not None: + return self.list_storage_class([self.remote_addr]) + return self.list_storage_class() + + @cached_property + def full_path(self) -> str: + """Requested path, including the query string.""" + return f"{self.path}?{_to_str(self.query_string, self.url_charset)}" + + @property + def is_secure(self) -> bool: + """``True`` if the request was made with a secure protocol + (HTTPS or WSS). + """ + return self.scheme in {"https", "wss"} + + @cached_property + def url(self) -> str: + """The full request URL with the scheme, host, root path, path, + and query string.""" + return get_current_url( + self.scheme, self.host, self.root_path, self.path, self.query_string + ) + + @cached_property + def base_url(self) -> str: + """Like :attr:`url` but without the query string.""" + return get_current_url(self.scheme, self.host, self.root_path, self.path) + + @cached_property + def root_url(self) -> str: + """The request URL scheme, host, and root path. This is the root + that the application is accessed from. + """ + return get_current_url(self.scheme, self.host, self.root_path) + + @cached_property + def host_url(self) -> str: + """The request URL scheme and host only.""" + return get_current_url(self.scheme, self.host) + + @cached_property + def host(self) -> str: + """The host name the request was made to, including the port if + it's non-standard. Validated with :attr:`trusted_hosts`. + """ + return get_host( + self.scheme, self.headers.get("host"), self.server, self.trusted_hosts + ) + + @cached_property + def cookies(self) -> "ImmutableMultiDict[str, str]": + """A :class:`dict` with the contents of all cookies transmitted with + the request.""" + wsgi_combined_cookie = ";".join(self.headers.getlist("Cookie")) + return parse_cookie( # type: ignore + wsgi_combined_cookie, + self.charset, + self.encoding_errors, + cls=self.dict_storage_class, + ) + + # Common Descriptors + + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + read_only=True, + ) + + @cached_property + def content_length(self) -> t.Optional[int]: + """The Content-Length entity-header field indicates the size of the + entity-body in bytes or, in the case of the HEAD method, the size of + the entity-body that would have been sent had the request been a + GET. + """ + if self.headers.get("Transfer-Encoding", "") == "chunked": + return None + + content_length = self.headers.get("Content-Length") + if content_length is not None: + try: + return max(0, int(content_length)) + except (ValueError, TypeError): + pass + + return None + + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field. + + .. versionadded:: 0.9""", + read_only=True, + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.) + + .. versionadded:: 0.9""", + read_only=True, + ) + referrer = header_property[str]( + "Referer", + doc="""The Referer[sic] request-header field allows the client + to specify, for the server's benefit, the address (URI) of the + resource from which the Request-URI was obtained (the + "referrer", although the header field is misspelled).""", + read_only=True, + ) + date = header_property( + "Date", + None, + parse_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + read_only=True, + ) + max_forwards = header_property( + "Max-Forwards", + None, + int, + doc="""The Max-Forwards request-header field provides a + mechanism with the TRACE and OPTIONS methods to limit the number + of proxies or gateways that can forward the request to the next + inbound server.""", + read_only=True, + ) + + def _parse_content_type(self) -> None: + if not hasattr(self, "_parsed_content_type"): + self._parsed_content_type = parse_options_header( + self.headers.get("Content-Type", "") + ) + + @property + def mimetype(self) -> str: + """Like :attr:`content_type`, but without parameters (eg, without + charset, type etc.) and always lowercase. For example if the content + type is ``text/HTML; charset=utf-8`` the mimetype would be + ``'text/html'``. + """ + self._parse_content_type() + return self._parsed_content_type[0].lower() + + @property + def mimetype_params(self) -> t.Dict[str, str]: + """The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + """ + self._parse_content_type() + return self._parsed_content_type[1] + + @cached_property + def pragma(self) -> HeaderSet: + """The Pragma general-header field is used to include + implementation-specific directives that might apply to any recipient + along the request/response chain. All pragma directives specify + optional behavior from the viewpoint of the protocol; however, some + systems MAY require that behavior be consistent with the directives. + """ + return parse_set_header(self.headers.get("Pragma", "")) + + # Accept + + @cached_property + def accept_mimetypes(self) -> MIMEAccept: + """List of mimetypes this client supports as + :class:`~werkzeug.datastructures.MIMEAccept` object. + """ + return parse_accept_header(self.headers.get("Accept"), MIMEAccept) + + @cached_property + def accept_charsets(self) -> CharsetAccept: + """List of charsets this client supports as + :class:`~werkzeug.datastructures.CharsetAccept` object. + """ + return parse_accept_header(self.headers.get("Accept-Charset"), CharsetAccept) + + @cached_property + def accept_encodings(self) -> Accept: + """List of encodings this client accepts. Encodings in a HTTP term + are compression encodings such as gzip. For charsets have a look at + :attr:`accept_charset`. + """ + return parse_accept_header(self.headers.get("Accept-Encoding")) + + @cached_property + def accept_languages(self) -> LanguageAccept: + """List of languages this client accepts as + :class:`~werkzeug.datastructures.LanguageAccept` object. + + .. versionchanged 0.5 + In previous versions this was a regular + :class:`~werkzeug.datastructures.Accept` object. + """ + return parse_accept_header(self.headers.get("Accept-Language"), LanguageAccept) + + # ETag + + @cached_property + def cache_control(self) -> RequestCacheControl: + """A :class:`~werkzeug.datastructures.RequestCacheControl` object + for the incoming cache control headers. + """ + cache_control = self.headers.get("Cache-Control") + return parse_cache_control_header(cache_control, None, RequestCacheControl) + + @cached_property + def if_match(self) -> ETags: + """An object containing all the etags in the `If-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-Match")) + + @cached_property + def if_none_match(self) -> ETags: + """An object containing all the etags in the `If-None-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-None-Match")) + + @cached_property + def if_modified_since(self) -> t.Optional[datetime]: + """The parsed `If-Modified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Modified-Since")) + + @cached_property + def if_unmodified_since(self) -> t.Optional[datetime]: + """The parsed `If-Unmodified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Unmodified-Since")) + + @cached_property + def if_range(self) -> IfRange: + """The parsed ``If-Range`` header. + + .. versionchanged:: 2.0 + ``IfRange.date`` is timezone-aware. + + .. versionadded:: 0.7 + """ + return parse_if_range_header(self.headers.get("If-Range")) + + @cached_property + def range(self) -> t.Optional[Range]: + """The parsed `Range` header. + + .. versionadded:: 0.7 + + :rtype: :class:`~werkzeug.datastructures.Range` + """ + return parse_range_header(self.headers.get("Range")) + + # User Agent + + @cached_property + def user_agent(self) -> UserAgent: + """The user agent. Use ``user_agent.string`` to get the header + value. Set :attr:`user_agent_class` to a subclass of + :class:`~werkzeug.user_agent.UserAgent` to provide parsing for + the other properties or other extended data. + + .. versionchanged:: 2.0 + The built in parser is deprecated and will be removed in + Werkzeug 2.1. A ``UserAgent`` subclass must be set to parse + data from the string. + """ + return self.user_agent_class(self.headers.get("User-Agent", "")) + + # Authorization + + @cached_property + def authorization(self) -> t.Optional[Authorization]: + """The `Authorization` object in parsed form.""" + return parse_authorization_header(self.headers.get("Authorization")) + + # CORS + + origin = header_property[str]( + "Origin", + doc=( + "The host that the request originated from. Set" + " :attr:`~CORSResponseMixin.access_control_allow_origin` on" + " the response to indicate which origins are allowed." + ), + read_only=True, + ) + + access_control_request_headers = header_property( + "Access-Control-Request-Headers", + load_func=parse_set_header, + doc=( + "Sent with a preflight request to indicate which headers" + " will be sent with the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_headers`" + " on the response to indicate which headers are allowed." + ), + read_only=True, + ) + + access_control_request_method = header_property[str]( + "Access-Control-Request-Method", + doc=( + "Sent with a preflight request to indicate which method" + " will be used for the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_methods`" + " on the response to indicate which methods are allowed." + ), + read_only=True, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/sansio/response.py b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/response.py new file mode 100644 index 0000000..82817e8 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/response.py @@ -0,0 +1,704 @@ +import typing as t +from datetime import datetime +from datetime import timedelta +from datetime import timezone +from http import HTTPStatus + +from .._internal import _to_str +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..http import dump_cookie +from ..http import HTTP_STATUS_CODES +from ..utils import get_content_type +from werkzeug.datastructures import CallbackDict +from werkzeug.datastructures import ContentRange +from werkzeug.datastructures import ContentSecurityPolicy +from werkzeug.datastructures import ResponseCacheControl +from werkzeug.datastructures import WWWAuthenticate +from werkzeug.http import COEP +from werkzeug.http import COOP +from werkzeug.http import dump_age +from werkzeug.http import dump_header +from werkzeug.http import dump_options_header +from werkzeug.http import http_date +from werkzeug.http import parse_age +from werkzeug.http import parse_cache_control_header +from werkzeug.http import parse_content_range_header +from werkzeug.http import parse_csp_header +from werkzeug.http import parse_date +from werkzeug.http import parse_options_header +from werkzeug.http import parse_set_header +from werkzeug.http import parse_www_authenticate_header +from werkzeug.http import quote_etag +from werkzeug.http import unquote_etag +from werkzeug.utils import header_property + + +def _set_property(name: str, doc: t.Optional[str] = None) -> property: + def fget(self: "Response") -> HeaderSet: + def on_update(header_set: HeaderSet) -> None: + if not header_set and name in self.headers: + del self.headers[name] + elif header_set: + self.headers[name] = header_set.to_header() + + return parse_set_header(self.headers.get(name), on_update) + + def fset( + self: "Response", + value: t.Optional[ + t.Union[str, t.Dict[str, t.Union[str, int]], t.Iterable[str]] + ], + ) -> None: + if not value: + del self.headers[name] + elif isinstance(value, str): + self.headers[name] = value + else: + self.headers[name] = dump_header(value) + + return property(fget, fset, doc=doc) + + +class Response: + """Represents the non-IO parts of an HTTP response, specifically the + status and headers but not the body. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Response`. + + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + + .. versionadded:: 2.0 + """ + + #: the charset of the response. + charset = "utf-8" + + #: the default status if none is provided. + default_status = 200 + + #: the default mimetype if none is provided. + default_mimetype = "text/plain" + + #: Warn if a cookie header exceeds this size. The default, 4093, should be + #: safely `supported by most browsers `_. A cookie larger than + #: this size will still be sent, but it may be ignored or handled + #: incorrectly by some browsers. Set to 0 to disable this check. + #: + #: .. versionadded:: 0.13 + #: + #: .. _`cookie`: http://browsercookielimits.squawky.net/ + max_cookie_size = 4093 + + # A :class:`Headers` object representing the response headers. + headers: Headers + + def __init__( + self, + status: t.Optional[t.Union[int, str, HTTPStatus]] = None, + headers: t.Optional[ + t.Union[ + t.Mapping[str, t.Union[str, int, t.Iterable[t.Union[str, int]]]], + t.Iterable[t.Tuple[str, t.Union[str, int]]], + ] + ] = None, + mimetype: t.Optional[str] = None, + content_type: t.Optional[str] = None, + ) -> None: + if isinstance(headers, Headers): + self.headers = headers + elif not headers: + self.headers = Headers() + else: + self.headers = Headers(headers) + + if content_type is None: + if mimetype is None and "content-type" not in self.headers: + mimetype = self.default_mimetype + if mimetype is not None: + mimetype = get_content_type(mimetype, self.charset) + content_type = mimetype + if content_type is not None: + self.headers["Content-Type"] = content_type + if status is None: + status = self.default_status + self.status = status # type: ignore + + def __repr__(self) -> str: + return f"<{type(self).__name__} [{self.status}]>" + + @property + def status_code(self) -> int: + """The HTTP status code as a number.""" + return self._status_code + + @status_code.setter + def status_code(self, code: int) -> None: + self.status = code # type: ignore + + @property + def status(self) -> str: + """The HTTP status code as a string.""" + return self._status + + @status.setter + def status(self, value: t.Union[str, int, HTTPStatus]) -> None: + if not isinstance(value, (str, bytes, int, HTTPStatus)): + raise TypeError("Invalid status argument") + + self._status, self._status_code = self._clean_status(value) + + def _clean_status(self, value: t.Union[str, int, HTTPStatus]) -> t.Tuple[str, int]: + if isinstance(value, HTTPStatus): + value = int(value) + status = _to_str(value, self.charset) + split_status = status.split(None, 1) + + if len(split_status) == 0: + raise ValueError("Empty status argument") + + if len(split_status) > 1: + if split_status[0].isdigit(): + # code and message + return status, int(split_status[0]) + + # multi-word message + return f"0 {status}", 0 + + if split_status[0].isdigit(): + # code only + status_code = int(split_status[0]) + + try: + status = f"{status_code} {HTTP_STATUS_CODES[status_code].upper()}" + except KeyError: + status = f"{status_code} UNKNOWN" + + return status, status_code + + # one-word message + return f"0 {status}", 0 + + def set_cookie( + self, + key: str, + value: str = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: t.Optional[str] = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Sets a cookie. + + A warning is raised if the size of the cookie header exceeds + :attr:`max_cookie_size`, but the header will still be set. + + :param key: the key (name) of the cookie to be set. + :param value: the value of the cookie. + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. + :param expires: should be a `datetime` object or UNIX timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: if you want to set a cross-domain cookie. For example, + ``domain=".example.com"`` will set a cookie that is + readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.headers.add( + "Set-Cookie", + dump_cookie( + key, + value=value, + max_age=max_age, + expires=expires, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + charset=self.charset, + max_size=self.max_cookie_size, + samesite=samesite, + ), + ) + + def delete_cookie( + self, + key: str, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Delete a cookie. Fails silently if key doesn't exist. + + :param key: the key (name) of the cookie to be deleted. + :param path: if the cookie that should be deleted was limited to a + path, the path has to be defined here. + :param domain: if the cookie that should be deleted was limited to a + domain, that domain has to be defined here. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.set_cookie( + key, + expires=0, + max_age=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return mt is not None and ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) + + # Common Descriptors + + @property + def mimetype(self) -> t.Optional[str]: + """The mimetype (content type without charset etc.)""" + ct = self.headers.get("content-type") + + if ct: + return ct.split(";")[0].strip() + else: + return None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.headers["Content-Type"] = get_content_type(value, self.charset) + + @property + def mimetype_params(self) -> t.Dict[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.5 + """ + + def on_update(d: CallbackDict) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + location = header_property[str]( + "Location", + doc="""The Location response-header field is used to redirect + the recipient to a location other than the Request-URI for + completion of the request or identification of a new + resource.""", + ) + age = header_property( + "Age", + None, + parse_age, + dump_age, # type: ignore + doc="""The Age response-header field conveys the sender's + estimate of the amount of time since the response (or its + revalidation) was generated at the origin server. + + Age values are non-negative decimal integers, representing time + in seconds.""", + ) + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + ) + content_length = header_property( + "Content-Length", + None, + int, + str, + doc="""The Content-Length entity-header field indicates the size + of the entity-body, in decimal number of OCTETs, sent to the + recipient or, in the case of the HEAD method, the size of the + entity-body that would have been sent had the request been a + GET.""", + ) + content_location = header_property[str]( + "Content-Location", + doc="""The Content-Location entity-header field MAY be used to + supply the resource location for the entity enclosed in the + message when that entity is accessible from a location separate + from the requested resource's URI.""", + ) + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field.""", + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.)""", + ) + date = header_property( + "Date", + None, + parse_date, + http_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + expires = header_property( + "Expires", + None, + parse_date, + http_date, + doc="""The Expires entity-header field gives the date/time after + which the response is considered stale. A stale cache entry may + not normally be returned by a cache. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + last_modified = header_property( + "Last-Modified", + None, + parse_date, + http_date, + doc="""The Last-Modified entity-header field indicates the date + and time at which the origin server believes the variant was + last modified. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + + @property + def retry_after(self) -> t.Optional[datetime]: + """The Retry-After response-header field can be used with a + 503 (Service Unavailable) response to indicate how long the + service is expected to be unavailable to the requesting client. + + Time in seconds until expiration or date. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + value = self.headers.get("retry-after") + if value is None: + return None + elif value.isdigit(): + return datetime.now(timezone.utc) + timedelta(seconds=int(value)) + return parse_date(value) + + @retry_after.setter + def retry_after(self, value: t.Optional[t.Union[datetime, int, str]]) -> None: + if value is None: + if "retry-after" in self.headers: + del self.headers["retry-after"] + return + elif isinstance(value, datetime): + value = http_date(value) + else: + value = str(value) + self.headers["Retry-After"] = value + + vary = _set_property( + "Vary", + doc="""The Vary field value indicates the set of request-header + fields that fully determines, while the response is fresh, + whether a cache is permitted to use the response to reply to a + subsequent request without revalidation.""", + ) + content_language = _set_property( + "Content-Language", + doc="""The Content-Language entity-header field describes the + natural language(s) of the intended audience for the enclosed + entity. Note that this might not be equivalent to all the + languages used within the entity-body.""", + ) + allow = _set_property( + "Allow", + doc="""The Allow entity-header field lists the set of methods + supported by the resource identified by the Request-URI. The + purpose of this field is strictly to inform the recipient of + valid methods associated with the resource. An Allow header + field MUST be present in a 405 (Method Not Allowed) + response.""", + ) + + # ETag + + @property + def cache_control(self) -> ResponseCacheControl: + """The Cache-Control general-header field is used to specify + directives that MUST be obeyed by all caching mechanisms along the + request/response chain. + """ + + def on_update(cache_control: ResponseCacheControl) -> None: + if not cache_control and "cache-control" in self.headers: + del self.headers["cache-control"] + elif cache_control: + self.headers["Cache-Control"] = cache_control.to_header() + + return parse_cache_control_header( + self.headers.get("cache-control"), on_update, ResponseCacheControl + ) + + def set_etag(self, etag: str, weak: bool = False) -> None: + """Set the etag, and override the old one if there was one.""" + self.headers["ETag"] = quote_etag(etag, weak) + + def get_etag(self) -> t.Union[t.Tuple[str, bool], t.Tuple[None, None]]: + """Return a tuple in the form ``(etag, is_weak)``. If there is no + ETag the return value is ``(None, None)``. + """ + return unquote_etag(self.headers.get("ETag")) + + accept_ranges = header_property[str]( + "Accept-Ranges", + doc="""The `Accept-Ranges` header. Even though the name would + indicate that multiple values are supported, it must be one + string token only. + + The values ``'bytes'`` and ``'none'`` are common. + + .. versionadded:: 0.7""", + ) + + @property + def content_range(self) -> ContentRange: + """The ``Content-Range`` header as a + :class:`~werkzeug.datastructures.ContentRange` object. Available + even if the header is not set. + + .. versionadded:: 0.7 + """ + + def on_update(rng: ContentRange) -> None: + if not rng: + del self.headers["content-range"] + else: + self.headers["Content-Range"] = rng.to_header() + + rv = parse_content_range_header(self.headers.get("content-range"), on_update) + # always provide a content range object to make the descriptor + # more user friendly. It provides an unset() method that can be + # used to remove the header quickly. + if rv is None: + rv = ContentRange(None, None, None, on_update=on_update) + return rv + + @content_range.setter + def content_range(self, value: t.Optional[t.Union[ContentRange, str]]) -> None: + if not value: + del self.headers["content-range"] + elif isinstance(value, str): + self.headers["Content-Range"] = value + else: + self.headers["Content-Range"] = value.to_header() + + # Authorization + + @property + def www_authenticate(self) -> WWWAuthenticate: + """The ``WWW-Authenticate`` header in a parsed form.""" + + def on_update(www_auth: WWWAuthenticate) -> None: + if not www_auth and "www-authenticate" in self.headers: + del self.headers["www-authenticate"] + elif www_auth: + self.headers["WWW-Authenticate"] = www_auth.to_header() + + header = self.headers.get("www-authenticate") + return parse_www_authenticate_header(header, on_update) + + # CSP + + @property + def content_security_policy(self) -> ContentSecurityPolicy: + """The ``Content-Security-Policy`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy header adds an additional layer of + security to help detect and mitigate certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy"] + else: + self.headers["Content-Security-Policy"] = csp.to_header() + + rv = parse_csp_header(self.headers.get("content-security-policy"), on_update) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy.setter + def content_security_policy( + self, value: t.Optional[t.Union[ContentSecurityPolicy, str]] + ) -> None: + if not value: + del self.headers["content-security-policy"] + elif isinstance(value, str): + self.headers["Content-Security-Policy"] = value + else: + self.headers["Content-Security-Policy"] = value.to_header() + + @property + def content_security_policy_report_only(self) -> ContentSecurityPolicy: + """The ``Content-Security-policy-report-only`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy-Report-Only header adds a csp policy + that is not enforced but is reported thereby helping detect + certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy-report-only"] + else: + self.headers["Content-Security-policy-report-only"] = csp.to_header() + + rv = parse_csp_header( + self.headers.get("content-security-policy-report-only"), on_update + ) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy_report_only.setter + def content_security_policy_report_only( + self, value: t.Optional[t.Union[ContentSecurityPolicy, str]] + ) -> None: + if not value: + del self.headers["content-security-policy-report-only"] + elif isinstance(value, str): + self.headers["Content-Security-policy-report-only"] = value + else: + self.headers["Content-Security-policy-report-only"] = value.to_header() + + # CORS + + @property + def access_control_allow_credentials(self) -> bool: + """Whether credentials can be shared by the browser to + JavaScript code. As part of the preflight request it indicates + whether credentials can be used on the cross origin request. + """ + return "Access-Control-Allow-Credentials" in self.headers + + @access_control_allow_credentials.setter + def access_control_allow_credentials(self, value: t.Optional[bool]) -> None: + if value is True: + self.headers["Access-Control-Allow-Credentials"] = "true" + else: + self.headers.pop("Access-Control-Allow-Credentials", None) + + access_control_allow_headers = header_property( + "Access-Control-Allow-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be sent with the cross origin request.", + ) + + access_control_allow_methods = header_property( + "Access-Control-Allow-Methods", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which methods can be used for the cross origin request.", + ) + + access_control_allow_origin = header_property[str]( + "Access-Control-Allow-Origin", + doc="The origin or '*' for any origin that may make cross origin requests.", + ) + + access_control_expose_headers = header_property( + "Access-Control-Expose-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be shared by the browser to JavaScript code.", + ) + + access_control_max_age = header_property( + "Access-Control-Max-Age", + load_func=int, + dump_func=str, + doc="The maximum age in seconds the access control settings can be cached for.", + ) + + cross_origin_opener_policy = header_property[COOP]( + "Cross-Origin-Opener-Policy", + load_func=lambda value: COOP(value), + dump_func=lambda value: value.value, + default=COOP.UNSAFE_NONE, + doc="""Allows control over sharing of browsing context group with cross-origin + documents. Values must be a member of the :class:`werkzeug.http.COOP` enum.""", + ) + + cross_origin_embedder_policy = header_property[COEP]( + "Cross-Origin-Embedder-Policy", + load_func=lambda value: COEP(value), + dump_func=lambda value: value.value, + default=COEP.UNSAFE_NONE, + doc="""Prevents a document from loading any cross-origin resources that do not + explicitly grant the document permission. Values must be a member of the + :class:`werkzeug.http.COEP` enum.""", + ) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/sansio/utils.py b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/utils.py new file mode 100644 index 0000000..1b4d892 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/sansio/utils.py @@ -0,0 +1,142 @@ +import typing as t + +from .._internal import _encode_idna +from ..exceptions import SecurityError +from ..urls import uri_to_iri +from ..urls import url_quote + + +def host_is_trusted(hostname: str, trusted_list: t.Iterable[str]) -> bool: + """Check if a host matches a list of trusted names. + + :param hostname: The name to check. + :param trusted_list: A list of valid names to match. If a name + starts with a dot it will match all subdomains. + + .. versionadded:: 0.9 + """ + if not hostname: + return False + + if isinstance(trusted_list, str): + trusted_list = [trusted_list] + + def _normalize(hostname: str) -> bytes: + if ":" in hostname: + hostname = hostname.rsplit(":", 1)[0] + + return _encode_idna(hostname) + + try: + hostname_bytes = _normalize(hostname) + except UnicodeError: + return False + + for ref in trusted_list: + if ref.startswith("."): + ref = ref[1:] + suffix_match = True + else: + suffix_match = False + + try: + ref_bytes = _normalize(ref) + except UnicodeError: + return False + + if ref_bytes == hostname_bytes: + return True + + if suffix_match and hostname_bytes.endswith(b"." + ref_bytes): + return True + + return False + + +def get_host( + scheme: str, + host_header: t.Optional[str], + server: t.Optional[t.Tuple[str, t.Optional[int]]] = None, + trusted_hosts: t.Optional[t.Iterable[str]] = None, +) -> str: + """Return the host for the given parameters. + + This first checks the ``host_header``. If it's not present, then + ``server`` is used. The host will only contain the port if it is + different than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param scheme: The protocol the request used, like ``"https"``. + :param host_header: The ``Host`` header value. + :param server: Address of the server. ``(host, port)``, or + ``(path, None)`` for unix sockets. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + host = "" + + if host_header is not None: + host = host_header + elif server is not None: + host = server[0] + + if server[1] is not None: + host = f"{host}:{server[1]}" + + if scheme in {"http", "ws"} and host.endswith(":80"): + host = host[:-3] + elif scheme in {"https", "wss"} and host.endswith(":443"): + host = host[:-4] + + if trusted_hosts is not None: + if not host_is_trusted(host, trusted_hosts): + raise SecurityError(f"Host {host!r} is not trusted.") + + return host + + +def get_current_url( + scheme: str, + host: str, + root_path: t.Optional[str] = None, + path: t.Optional[str] = None, + query_string: t.Optional[bytes] = None, +) -> str: + """Recreate the URL for a request. If an optional part isn't + provided, it and subsequent parts are not included in the URL. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param scheme: The protocol the request used, like ``"https"``. + :param host: The host the request was made to. See :func:`get_host`. + :param root_path: Prefix that the application is mounted under. This + is prepended to ``path``. + :param path: The path part of the URL after ``root_path``. + :param query_string: The portion of the URL after the "?". + """ + url = [scheme, "://", host] + + if root_path is None: + url.append("/") + return uri_to_iri("".join(url)) + + url.append(url_quote(root_path.rstrip("/"))) + url.append("/") + + if path is None: + return uri_to_iri("".join(url)) + + url.append(url_quote(path.lstrip("/"))) + + if query_string: + url.append("?") + url.append(url_quote(query_string, safe=":&%=+$!*'(),")) + + return uri_to_iri("".join(url)) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/security.py b/axios-example/lib/python3.10/site-packages/werkzeug/security.py new file mode 100644 index 0000000..18d0919 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/security.py @@ -0,0 +1,140 @@ +import hashlib +import hmac +import os +import posixpath +import secrets +import typing as t + +if t.TYPE_CHECKING: + pass + +SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +DEFAULT_PBKDF2_ITERATIONS = 260000 + +_os_alt_seps: t.List[str] = list( + sep for sep in [os.path.sep, os.path.altsep] if sep is not None and sep != "/" +) + + +def gen_salt(length: int) -> str: + """Generate a random string of SALT_CHARS with specified ``length``.""" + if length <= 0: + raise ValueError("Salt length must be positive") + + return "".join(secrets.choice(SALT_CHARS) for _ in range(length)) + + +def _hash_internal(method: str, salt: str, password: str) -> t.Tuple[str, str]: + """Internal password hash helper. Supports plaintext without salt, + unsalted and salted passwords. In case salted passwords are used + hmac is used. + """ + if method == "plain": + return password, method + + salt = salt.encode("utf-8") + password = password.encode("utf-8") + + if method.startswith("pbkdf2:"): + if not salt: + raise ValueError("Salt is required for PBKDF2") + + args = method[7:].split(":") + + if len(args) not in (1, 2): + raise ValueError("Invalid number of arguments for PBKDF2") + + method = args.pop(0) + iterations = int(args[0] or 0) if args else DEFAULT_PBKDF2_ITERATIONS + return ( + hashlib.pbkdf2_hmac(method, password, salt, iterations).hex(), + f"pbkdf2:{method}:{iterations}", + ) + + if salt: + return hmac.new(salt, password, method).hexdigest(), method + + return hashlib.new(method, password).hexdigest(), method + + +def generate_password_hash( + password: str, method: str = "pbkdf2:sha256", salt_length: int = 16 +) -> str: + """Hash a password with the given method and salt with a string of + the given length. The format of the string returned includes the method + that was used so that :func:`check_password_hash` can check the hash. + + The format for the hashed string looks like this:: + + method$salt$hash + + This method can **not** generate unsalted passwords but it is possible + to set param method='plain' in order to enforce plaintext passwords. + If a salt is used, hmac is used internally to salt the password. + + If PBKDF2 is wanted it can be enabled by setting the method to + ``pbkdf2:method:iterations`` where iterations is optional:: + + pbkdf2:sha256:80000$salt$hash + pbkdf2:sha256$salt$hash + + :param password: the password to hash. + :param method: the hash method to use (one that hashlib supports). Can + optionally be in the format ``pbkdf2:method:iterations`` + to enable PBKDF2. + :param salt_length: the length of the salt in letters. + """ + salt = gen_salt(salt_length) if method != "plain" else "" + h, actual_method = _hash_internal(method, salt, password) + return f"{actual_method}${salt}${h}" + + +def check_password_hash(pwhash: str, password: str) -> bool: + """Check a password against a given salted and hashed password value. + In order to support unsalted legacy passwords this method supports + plain text passwords, md5 and sha1 hashes (both salted and unsalted). + + Returns `True` if the password matched, `False` otherwise. + + :param pwhash: a hashed string like returned by + :func:`generate_password_hash`. + :param password: the plaintext password to compare against the hash. + """ + if pwhash.count("$") < 2: + return False + + method, salt, hashval = pwhash.split("$", 2) + return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval) + + +def safe_join(directory: str, *pathnames: str) -> t.Optional[str]: + """Safely join zero or more untrusted path components to a base + directory to avoid escaping the base directory. + + :param directory: The trusted base directory. + :param pathnames: The untrusted path components relative to the + base directory. + :return: A safe path, otherwise ``None``. + """ + if not directory: + # Ensure we end up with ./path if directory="" is given, + # otherwise the first untrusted part could become trusted. + directory = "." + + parts = [directory] + + for filename in pathnames: + if filename != "": + filename = posixpath.normpath(filename) + + if ( + any(sep in filename for sep in _os_alt_seps) + or os.path.isabs(filename) + or filename == ".." + or filename.startswith("../") + ): + return None + + parts.append(filename) + + return posixpath.join(*parts) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/serving.py b/axios-example/lib/python3.10/site-packages/werkzeug/serving.py new file mode 100644 index 0000000..7123076 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/serving.py @@ -0,0 +1,1091 @@ +"""A WSGI and HTTP server for use **during development only**. This +server is convenient to use, but is not designed to be particularly +stable, secure, or efficient. Use a dedicate WSGI server and HTTP +server when deploying to production. + +It provides features like interactive debugging and code reloading. Use +``run_simple`` to start the server. Put this in a ``run.py`` script: + +.. code-block:: python + + from myapp import create_app + from werkzeug import run_simple +""" +import errno +import io +import os +import socket +import socketserver +import sys +import typing as t +from datetime import datetime as dt +from datetime import timedelta +from datetime import timezone +from http.server import BaseHTTPRequestHandler +from http.server import HTTPServer + +from ._internal import _log +from ._internal import _wsgi_encoding_dance +from .exceptions import InternalServerError +from .urls import uri_to_iri +from .urls import url_parse +from .urls import url_unquote + +try: + import ssl +except ImportError: + + class _SslDummy: + def __getattr__(self, name: str) -> t.Any: + raise RuntimeError( # noqa: B904 + "SSL is unavailable because this Python runtime was not" + " compiled with SSL/TLS support." + ) + + ssl = _SslDummy() # type: ignore + +_log_add_style = True + +if os.name == "nt": + try: + __import__("colorama") + except ImportError: + _log_add_style = False + +can_fork = hasattr(os, "fork") + +if can_fork: + ForkingMixIn = socketserver.ForkingMixIn +else: + + class ForkingMixIn: # type: ignore + pass + + +try: + af_unix = socket.AF_UNIX +except AttributeError: + af_unix = None # type: ignore + +LISTEN_QUEUE = 128 + +_TSSLContextArg = t.Optional[ + t.Union["ssl.SSLContext", t.Tuple[str, t.Optional[str]], "te.Literal['adhoc']"] +] + +if t.TYPE_CHECKING: + import typing_extensions as te # noqa: F401 + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKeyWithSerialization, + ) + from cryptography.x509 import Certificate + + +class DechunkedInput(io.RawIOBase): + """An input stream that handles Transfer-Encoding 'chunked'""" + + def __init__(self, rfile: t.IO[bytes]) -> None: + self._rfile = rfile + self._done = False + self._len = 0 + + def readable(self) -> bool: + return True + + def read_chunk_len(self) -> int: + try: + line = self._rfile.readline().decode("latin1") + _len = int(line.strip(), 16) + except ValueError as e: + raise OSError("Invalid chunk header") from e + if _len < 0: + raise OSError("Negative chunk length not allowed") + return _len + + def readinto(self, buf: bytearray) -> int: # type: ignore + read = 0 + while not self._done and read < len(buf): + if self._len == 0: + # This is the first chunk or we fully consumed the previous + # one. Read the next length of the next chunk + self._len = self.read_chunk_len() + + if self._len == 0: + # Found the final chunk of size 0. The stream is now exhausted, + # but there is still a final newline that should be consumed + self._done = True + + if self._len > 0: + # There is data (left) in this chunk, so append it to the + # buffer. If this operation fully consumes the chunk, this will + # reset self._len to 0. + n = min(len(buf), self._len) + + # If (read + chunk size) becomes more than len(buf), buf will + # grow beyond the original size and read more data than + # required. So only read as much data as can fit in buf. + if read + n > len(buf): + buf[read:] = self._rfile.read(len(buf) - read) + self._len -= len(buf) - read + read = len(buf) + else: + buf[read : read + n] = self._rfile.read(n) + self._len -= n + read += n + + if self._len == 0: + # Skip the terminating newline of a chunk that has been fully + # consumed. This also applies to the 0-sized final chunk + terminator = self._rfile.readline() + if terminator not in (b"\n", b"\r\n", b"\r"): + raise OSError("Missing chunk terminating newline") + + return read + + +class WSGIRequestHandler(BaseHTTPRequestHandler): + """A request handler that implements WSGI dispatching.""" + + server: "BaseWSGIServer" + + @property + def server_version(self) -> str: # type: ignore + from . import __version__ + + return f"Werkzeug/{__version__}" + + def make_environ(self) -> "WSGIEnvironment": + request_url = url_parse(self.path) + url_scheme = "http" if self.server.ssl_context is None else "https" + + if not self.client_address: + self.client_address = ("", 0) + elif isinstance(self.client_address, str): + self.client_address = (self.client_address, 0) + + # If there was no scheme but the path started with two slashes, + # the first segment may have been incorrectly parsed as the + # netloc, prepend it to the path again. + if not request_url.scheme and request_url.netloc: + path_info = f"/{request_url.netloc}{request_url.path}" + else: + path_info = request_url.path + + path_info = url_unquote(path_info) + + environ: "WSGIEnvironment" = { + "wsgi.version": (1, 0), + "wsgi.url_scheme": url_scheme, + "wsgi.input": self.rfile, + "wsgi.errors": sys.stderr, + "wsgi.multithread": self.server.multithread, + "wsgi.multiprocess": self.server.multiprocess, + "wsgi.run_once": False, + "werkzeug.socket": self.connection, + "SERVER_SOFTWARE": self.server_version, + "REQUEST_METHOD": self.command, + "SCRIPT_NAME": "", + "PATH_INFO": _wsgi_encoding_dance(path_info), + "QUERY_STRING": _wsgi_encoding_dance(request_url.query), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": _wsgi_encoding_dance(self.path), + # Non-standard, added by gunicorn + "RAW_URI": _wsgi_encoding_dance(self.path), + "REMOTE_ADDR": self.address_string(), + "REMOTE_PORT": self.port_integer(), + "SERVER_NAME": self.server.server_address[0], + "SERVER_PORT": str(self.server.server_address[1]), + "SERVER_PROTOCOL": self.request_version, + } + + for key, value in self.headers.items(): + key = key.upper().replace("-", "_") + value = value.replace("\r\n", "") + if key not in ("CONTENT_TYPE", "CONTENT_LENGTH"): + key = f"HTTP_{key}" + if key in environ: + value = f"{environ[key]},{value}" + environ[key] = value + + if environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked": + environ["wsgi.input_terminated"] = True + environ["wsgi.input"] = DechunkedInput(environ["wsgi.input"]) + + # Per RFC 2616, if the URL is absolute, use that as the host. + # We're using "has a scheme" to indicate an absolute URL. + if request_url.scheme and request_url.netloc: + environ["HTTP_HOST"] = request_url.netloc + + try: + # binary_form=False gives nicer information, but wouldn't be compatible with + # what Nginx or Apache could return. + peer_cert = self.connection.getpeercert( # type: ignore[attr-defined] + binary_form=True + ) + if peer_cert is not None: + # Nginx and Apache use PEM format. + environ["SSL_CLIENT_CERT"] = ssl.DER_cert_to_PEM_cert(peer_cert) + except ValueError: + # SSL handshake hasn't finished. + self.server.log("error", "Cannot fetch SSL peer certificate info") + except AttributeError: + # Not using TLS, the socket will not have getpeercert(). + pass + + return environ + + def run_wsgi(self) -> None: + if self.headers.get("Expect", "").lower().strip() == "100-continue": + self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") + + self.environ = environ = self.make_environ() + status_set: t.Optional[str] = None + headers_set: t.Optional[t.List[t.Tuple[str, str]]] = None + status_sent: t.Optional[str] = None + headers_sent: t.Optional[t.List[t.Tuple[str, str]]] = None + chunk_response: bool = False + + def write(data: bytes) -> None: + nonlocal status_sent, headers_sent, chunk_response + assert status_set is not None, "write() before start_response" + assert headers_set is not None, "write() before start_response" + if status_sent is None: + status_sent = status_set + headers_sent = headers_set + try: + code_str, msg = status_sent.split(None, 1) + except ValueError: + code_str, msg = status_sent, "" + code = int(code_str) + self.send_response(code, msg) + header_keys = set() + for key, value in headers_sent: + self.send_header(key, value) + header_keys.add(key.lower()) + + # Use chunked transfer encoding if there is no content + # length. Do not use for 1xx and 204 responses. 304 + # responses and HEAD requests are also excluded, which + # is the more conservative behavior and matches other + # parts of the code. + # https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.1 + if ( + not ( + "content-length" in header_keys + or environ["REQUEST_METHOD"] == "HEAD" + or (100 <= code < 200) + or code in {204, 304} + ) + and self.protocol_version >= "HTTP/1.1" + ): + chunk_response = True + self.send_header("Transfer-Encoding", "chunked") + + # Always close the connection. This disables HTTP/1.1 + # keep-alive connections. They aren't handled well by + # Python's http.server because it doesn't know how to + # drain the stream before the next request line. + self.send_header("Connection", "close") + self.end_headers() + + assert isinstance(data, bytes), "applications must write bytes" + + if data: + if chunk_response: + self.wfile.write(hex(len(data))[2:].encode()) + self.wfile.write(b"\r\n") + + self.wfile.write(data) + + if chunk_response: + self.wfile.write(b"\r\n") + + self.wfile.flush() + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal status_set, headers_set + if exc_info: + try: + if headers_sent: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + elif headers_set: + raise AssertionError("Headers already set") + status_set = status + headers_set = headers + return write + + def execute(app: "WSGIApplication") -> None: + application_iter = app(environ, start_response) + try: + for data in application_iter: + write(data) + if not headers_sent: + write(b"") + if chunk_response: + self.wfile.write(b"0\r\n\r\n") + finally: + if hasattr(application_iter, "close"): + application_iter.close() # type: ignore + + try: + execute(self.server.app) + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e, environ) + except Exception as e: + if self.server.passthrough_errors: + raise + + if status_sent is not None and chunk_response: + self.close_connection = True + + try: + # if we haven't yet sent the headers but they are set + # we roll back to be able to set them again. + if status_sent is None: + status_set = None + headers_set = None + execute(InternalServerError()) + except Exception: + pass + + from .debug.tbtools import DebugTraceback + + msg = DebugTraceback(e).render_traceback_text() + self.server.log("error", f"Error on request:\n{msg}") + + def handle(self) -> None: + """Handles a request ignoring dropped connections.""" + try: + super().handle() + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e) + except Exception as e: + if self.server.ssl_context is not None and is_ssl_error(e): + self.log_error("SSL error occurred: %s", e) + else: + raise + + def connection_dropped( + self, error: BaseException, environ: t.Optional["WSGIEnvironment"] = None + ) -> None: + """Called if the connection was closed by the client. By default + nothing happens. + """ + + def __getattr__(self, name: str) -> t.Any: + # All HTTP methods are handled by run_wsgi. + if name.startswith("do_"): + return self.run_wsgi + + # All other attributes are forwarded to the base class. + return getattr(super(), name) + + def address_string(self) -> str: + if getattr(self, "environ", None): + return self.environ["REMOTE_ADDR"] # type: ignore + + if not self.client_address: + return "" + + return self.client_address[0] + + def port_integer(self) -> int: + return self.client_address[1] + + def log_request( + self, code: t.Union[int, str] = "-", size: t.Union[int, str] = "-" + ) -> None: + try: + path = uri_to_iri(self.path) + msg = f"{self.command} {path} {self.request_version}" + except AttributeError: + # path isn't set if the requestline was bad + msg = self.requestline + + code = str(code) + + if _log_add_style: + if code[0] == "1": # 1xx - Informational + msg = _ansi_style(msg, "bold") + elif code == "200": # 2xx - Success + pass + elif code == "304": # 304 - Resource Not Modified + msg = _ansi_style(msg, "cyan") + elif code[0] == "3": # 3xx - Redirection + msg = _ansi_style(msg, "green") + elif code == "404": # 404 - Resource Not Found + msg = _ansi_style(msg, "yellow") + elif code[0] == "4": # 4xx - Client Error + msg = _ansi_style(msg, "bold", "red") + else: # 5xx, or any other response + msg = _ansi_style(msg, "bold", "magenta") + + self.log("info", '"%s" %s %s', msg, code, size) + + def log_error(self, format: str, *args: t.Any) -> None: + self.log("error", format, *args) + + def log_message(self, format: str, *args: t.Any) -> None: + self.log("info", format, *args) + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log( + type, + f"{self.address_string()} - - [{self.log_date_time_string()}] {message}\n", + *args, + ) + + +def _ansi_style(value: str, *styles: str) -> str: + codes = { + "bold": 1, + "red": 31, + "green": 32, + "yellow": 33, + "magenta": 35, + "cyan": 36, + } + + for style in styles: + value = f"\x1b[{codes[style]}m{value}" + + return f"{value}\x1b[0m" + + +def generate_adhoc_ssl_pair( + cn: t.Optional[str] = None, +) -> t.Tuple["Certificate", "RSAPrivateKeyWithSerialization"]: + try: + from cryptography import x509 + from cryptography.x509.oid import NameOID + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import rsa + except ImportError: + raise TypeError( + "Using ad-hoc certificates requires the cryptography library." + ) from None + + backend = default_backend() + pkey = rsa.generate_private_key( + public_exponent=65537, key_size=2048, backend=backend + ) + + # pretty damn sure that this is not actually accepted by anyone + if cn is None: + cn = "*" + + subject = x509.Name( + [ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Dummy Certificate"), + x509.NameAttribute(NameOID.COMMON_NAME, cn), + ] + ) + + backend = default_backend() + cert = ( + x509.CertificateBuilder() + .subject_name(subject) + .issuer_name(subject) + .public_key(pkey.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(dt.now(timezone.utc)) + .not_valid_after(dt.now(timezone.utc) + timedelta(days=365)) + .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False) + .add_extension(x509.SubjectAlternativeName([x509.DNSName(cn)]), critical=False) + .sign(pkey, hashes.SHA256(), backend) + ) + return cert, pkey + + +def make_ssl_devcert( + base_path: str, host: t.Optional[str] = None, cn: t.Optional[str] = None +) -> t.Tuple[str, str]: + """Creates an SSL key for development. This should be used instead of + the ``'adhoc'`` key which generates a new cert on each server start. + It accepts a path for where it should store the key and cert and + either a host or CN. If a host is given it will use the CN + ``*.host/CN=host``. + + For more information see :func:`run_simple`. + + .. versionadded:: 0.9 + + :param base_path: the path to the certificate and key. The extension + ``.crt`` is added for the certificate, ``.key`` is + added for the key. + :param host: the name of the host. This can be used as an alternative + for the `cn`. + :param cn: the `CN` to use. + """ + + if host is not None: + cn = f"*.{host}/CN={host}" + cert, pkey = generate_adhoc_ssl_pair(cn=cn) + + from cryptography.hazmat.primitives import serialization + + cert_file = f"{base_path}.crt" + pkey_file = f"{base_path}.key" + + with open(cert_file, "wb") as f: + f.write(cert.public_bytes(serialization.Encoding.PEM)) + with open(pkey_file, "wb") as f: + f.write( + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + ) + + return cert_file, pkey_file + + +def generate_adhoc_ssl_context() -> "ssl.SSLContext": + """Generates an adhoc SSL context for the development server.""" + import tempfile + import atexit + + cert, pkey = generate_adhoc_ssl_pair() + + from cryptography.hazmat.primitives import serialization + + cert_handle, cert_file = tempfile.mkstemp() + pkey_handle, pkey_file = tempfile.mkstemp() + atexit.register(os.remove, pkey_file) + atexit.register(os.remove, cert_file) + + os.write(cert_handle, cert.public_bytes(serialization.Encoding.PEM)) + os.write( + pkey_handle, + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ), + ) + + os.close(cert_handle) + os.close(pkey_handle) + ctx = load_ssl_context(cert_file, pkey_file) + return ctx + + +def load_ssl_context( + cert_file: str, pkey_file: t.Optional[str] = None, protocol: t.Optional[int] = None +) -> "ssl.SSLContext": + """Loads SSL context from cert/private key files and optional protocol. + Many parameters are directly taken from the API of + :py:class:`ssl.SSLContext`. + + :param cert_file: Path of the certificate to use. + :param pkey_file: Path of the private key to use. If not given, the key + will be obtained from the certificate file. + :param protocol: A ``PROTOCOL`` constant from the :mod:`ssl` module. + Defaults to :data:`ssl.PROTOCOL_TLS_SERVER`. + """ + if protocol is None: + protocol = ssl.PROTOCOL_TLS_SERVER + + ctx = ssl.SSLContext(protocol) + ctx.load_cert_chain(cert_file, pkey_file) + return ctx + + +def is_ssl_error(error: t.Optional[Exception] = None) -> bool: + """Checks if the given error (or the current one) is an SSL error.""" + if error is None: + error = t.cast(Exception, sys.exc_info()[1]) + return isinstance(error, ssl.SSLError) + + +def select_address_family(host: str, port: int) -> socket.AddressFamily: + """Return ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending on + the host and port.""" + if host.startswith("unix://"): + return socket.AF_UNIX + elif ":" in host and hasattr(socket, "AF_INET6"): + return socket.AF_INET6 + return socket.AF_INET + + +def get_sockaddr( + host: str, port: int, family: socket.AddressFamily +) -> t.Union[t.Tuple[str, int], str]: + """Return a fully qualified socket address that can be passed to + :func:`socket.bind`.""" + if family == af_unix: + return host.split("://", 1)[1] + try: + res = socket.getaddrinfo( + host, port, family, socket.SOCK_STREAM, socket.IPPROTO_TCP + ) + except socket.gaierror: + return host, port + return res[0][4] # type: ignore + + +def get_interface_ip(family: socket.AddressFamily) -> str: + """Get the IP address of an external interface. Used when binding to + 0.0.0.0 or ::1 to show a more useful URL. + + :meta private: + """ + # arbitrary private address + host = "fd31:f903:5ab5:1::1" if family == socket.AF_INET6 else "10.253.155.219" + + with socket.socket(family, socket.SOCK_DGRAM) as s: + try: + s.connect((host, 58162)) + except OSError: + return "::1" if family == socket.AF_INET6 else "127.0.0.1" + + return s.getsockname()[0] # type: ignore + + +class BaseWSGIServer(HTTPServer): + """A WSGI server that that handles one request at a time. + + Use :func:`make_server` to create a server instance. + """ + + multithread = False + multiprocess = False + request_queue_size = LISTEN_QUEUE + + def __init__( + self, + host: str, + port: int, + app: "WSGIApplication", + handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, + ) -> None: + if handler is None: + handler = WSGIRequestHandler + + # If the handler doesn't directly set a protocol version and + # thread or process workers are used, then allow chunked + # responses and keep-alive connections by enabling HTTP/1.1. + if "protocol_version" not in vars(handler) and ( + self.multithread or self.multiprocess + ): + handler.protocol_version = "HTTP/1.1" + + self.host = host + self.port = port + self.app = app + self.passthrough_errors = passthrough_errors + + self.address_family = address_family = select_address_family(host, port) + server_address = get_sockaddr(host, int(port), address_family) + + # Remove a leftover Unix socket file from a previous run. Don't + # remove a file that was set up by run_simple. + if address_family == af_unix and fd is None: + server_address = t.cast(str, server_address) + + if os.path.exists(server_address): + os.unlink(server_address) + + # Bind and activate will be handled manually, it should only + # happen if we're not using a socket that was already set up. + super().__init__( + server_address, # type: ignore[arg-type] + handler, + bind_and_activate=False, + ) + + if fd is None: + # No existing socket descriptor, do bind_and_activate=True. + try: + self.server_bind() + self.server_activate() + except BaseException: + self.server_close() + raise + else: + # Use the passed in socket directly. + self.socket = socket.fromfd(fd, address_family, socket.SOCK_STREAM) + self.server_address = self.socket.getsockname() + + if address_family != af_unix: + # If port was 0, this will record the bound port. + self.port = self.server_address[1] + + if ssl_context is not None: + if isinstance(ssl_context, tuple): + ssl_context = load_ssl_context(*ssl_context) + elif ssl_context == "adhoc": + ssl_context = generate_adhoc_ssl_context() + + self.socket = ssl_context.wrap_socket(self.socket, server_side=True) + self.ssl_context: t.Optional["ssl.SSLContext"] = ssl_context + else: + self.ssl_context = None + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log(type, message, *args) + + def serve_forever(self, poll_interval: float = 0.5) -> None: + try: + super().serve_forever(poll_interval=poll_interval) + except KeyboardInterrupt: + pass + finally: + self.server_close() + + def handle_error( + self, request: t.Any, client_address: t.Union[t.Tuple[str, int], str] + ) -> None: + if self.passthrough_errors: + raise + + return super().handle_error(request, client_address) + + def log_startup(self) -> None: + """Show information about the address when starting the server.""" + if self.address_family == af_unix: + _log("info", f" * Running on {self.host} (Press CTRL+C to quit)") + else: + scheme = "http" if self.ssl_context is None else "https" + messages = [] + all_addresses_message = ( + f" * Running on all addresses ({self.host})\n" + " WARNING: This is a development server. Do not use it in" + " a production deployment." + ) + + if self.host == "0.0.0.0": + messages.append(all_addresses_message) + messages.append(f" * Running on {scheme}://127.0.0.1:{self.port}") + display_hostname = get_interface_ip(socket.AF_INET) + elif self.host == "::": + messages.append(all_addresses_message) + messages.append(f" * Running on {scheme}://[::1]:{self.port}") + display_hostname = get_interface_ip(socket.AF_INET6) + else: + display_hostname = self.host + + if ":" in display_hostname: + display_hostname = f"[{display_hostname}]" + + messages.append( + f" * Running on {scheme}://{display_hostname}:{self.port}" + " (Press CTRL+C to quit)" + ) + _log("info", "\n".join(messages)) + + +class ThreadedWSGIServer(socketserver.ThreadingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate + threads. + + Use :func:`make_server` to create a server instance. + """ + + multithread = True + daemon_threads = True + + +class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate forked + processes. + + Use :func:`make_server` to create a server instance. + """ + + multiprocess = True + + def __init__( + self, + host: str, + port: int, + app: "WSGIApplication", + processes: int = 40, + handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, + ) -> None: + if not can_fork: + raise ValueError("Your platform does not support forking.") + + super().__init__(host, port, app, handler, passthrough_errors, ssl_context, fd) + self.max_children = processes + + +def make_server( + host: str, + port: int, + app: "WSGIApplication", + threaded: bool = False, + processes: int = 1, + request_handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, +) -> BaseWSGIServer: + """Create an appropriate WSGI server instance based on the value of + ``threaded`` and ``processes``. + + This is called from :func:`run_simple`, but can be used separately + to have access to the server object, such as to run it in a separate + thread. + + See :func:`run_simple` for parameter docs. + """ + if threaded and processes > 1: + raise ValueError("Cannot have a multi-thread and multi-process server.") + + if threaded: + return ThreadedWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + if processes > 1: + return ForkingWSGIServer( + host, + port, + app, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + + return BaseWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + +def is_running_from_reloader() -> bool: + """Check if the server is running as a subprocess within the + Werkzeug reloader. + + .. versionadded:: 0.10 + """ + return os.environ.get("WERKZEUG_RUN_MAIN") == "true" + + +def prepare_socket(hostname: str, port: int) -> socket.socket: + """Prepare a socket for use by the WSGI server and reloader. + + The socket is marked inheritable so that it can be kept across + reloads instead of breaking connections. + + Catch errors during bind and show simpler error messages. For + "address already in use", show instructions for resolving the issue, + with special instructions for macOS. + + This is called from :func:`run_simple`, but can be used separately + to control server creation with :func:`make_server`. + """ + address_family = select_address_family(hostname, port) + server_address = get_sockaddr(hostname, port, address_family) + s = socket.socket(address_family, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.set_inheritable(True) + + # Remove the socket file if it already exists. + if address_family == af_unix: + server_address = t.cast(str, server_address) + + if os.path.exists(server_address): + os.unlink(server_address) + + # Catch connection issues and show them without the traceback. Show + # extra instructions for address not found, and for macOS. + try: + s.bind(server_address) + except OSError as e: + print(e.strerror, file=sys.stderr) + + if e.errno == errno.EADDRINUSE: + print( + f"Port {port} is in use by another program. Either" + " identify and stop that program, or start the" + " server with a different port.", + file=sys.stderr, + ) + + if sys.platform == "darwin" and port == 5000: + print( + "On macOS, try disabling the 'AirPlay Receiver'" + " service from System Preferences -> Sharing.", + file=sys.stderr, + ) + + sys.exit(1) + + s.listen(LISTEN_QUEUE) + return s + + +def run_simple( + hostname: str, + port: int, + application: "WSGIApplication", + use_reloader: bool = False, + use_debugger: bool = False, + use_evalex: bool = True, + extra_files: t.Optional[t.Iterable[str]] = None, + exclude_patterns: t.Optional[t.Iterable[str]] = None, + reloader_interval: int = 1, + reloader_type: str = "auto", + threaded: bool = False, + processes: int = 1, + request_handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + static_files: t.Optional[t.Dict[str, t.Union[str, t.Tuple[str, str]]]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, +) -> None: + """Start a development server for a WSGI application. Various + optional features can be enabled. + + .. warning:: + + Do not use the development server when deploying to production. + It is intended for use only during local development. It is not + designed to be particularly efficient, stable, or secure. + + :param hostname: The host to bind to, for example ``'localhost'``. + Can be a domain, IPv4 or IPv6 address, or file path starting + with ``unix://`` for a Unix socket. + :param port: The port to bind to, for example ``8080``. Using ``0`` + tells the OS to pick a random free port. + :param application: The WSGI application to run. + :param use_reloader: Use a reloader process to restart the server + process when files are changed. + :param use_debugger: Use Werkzeug's debugger, which will show + formatted tracebacks on unhandled exceptions. + :param use_evalex: Make the debugger interactive. A Python terminal + can be opened for any frame in the traceback. Some protection is + provided by requiring a PIN, but this should never be enabled + on a publicly visible server. + :param extra_files: The reloader will watch these files for changes + in addition to Python modules. For example, watch a + configuration file. + :param exclude_patterns: The reloader will ignore changes to any + files matching these :mod:`fnmatch` patterns. For example, + ignore cache files. + :param reloader_interval: How often the reloader tries to check for + changes. + :param reloader_type: The reloader to use. The ``'stat'`` reloader + is built in, but may require significant CPU to watch files. The + ``'watchdog'`` reloader is much more efficient but requires + installing the ``watchdog`` package first. + :param threaded: Handle concurrent requests using threads. Cannot be + used with ``processes``. + :param processes: Handle concurrent requests using up to this number + of processes. Cannot be used with ``threaded``. + :param request_handler: Use a different + :class:`~BaseHTTPServer.BaseHTTPRequestHandler` subclass to + handle requests. + :param static_files: A dict mapping URL prefixes to directories to + serve static files from using + :class:`~werkzeug.middleware.SharedDataMiddleware`. + :param passthrough_errors: Don't catch unhandled exceptions at the + server level, let the serve crash instead. If ``use_debugger`` + is enabled, the debugger will still catch such errors. + :param ssl_context: Configure TLS to serve over HTTPS. Can be an + :class:`ssl.SSLContext` object, a ``(cert_file, key_file)`` + tuple to create a typical context, or the string ``'adhoc'`` to + generate a temporary self-signed certificate. + + .. versionchanged:: 2.1 + Instructions are shown for dealing with an "address already in + use" error. + + .. versionchanged:: 2.1 + Running on ``0.0.0.0`` or ``::`` shows the loopback IP in + addition to a real IP. + + .. versionchanged:: 2.1 + The command-line interface was removed. + + .. versionchanged:: 2.0 + Running on ``0.0.0.0`` or ``::`` shows a real IP address that + was bound as well as a warning not to run the development server + in production. + + .. versionchanged:: 2.0 + The ``exclude_patterns`` parameter was added. + + .. versionchanged:: 0.15 + Bind to a Unix socket by passing a ``hostname`` that starts with + ``unix://``. + + .. versionchanged:: 0.10 + Improved the reloader and added support for changing the backend + through the ``reloader_type`` parameter. + + .. versionchanged:: 0.9 + A command-line interface was added. + + .. versionchanged:: 0.8 + ``ssl_context`` can be a tuple of paths to the certificate and + private key files. + + .. versionchanged:: 0.6 + The ``ssl_context`` parameter was added. + + .. versionchanged:: 0.5 + The ``static_files`` and ``passthrough_errors`` parameters were + added. + """ + if not isinstance(port, int): + raise TypeError("port must be an integer") + + if static_files: + from .middleware.shared_data import SharedDataMiddleware + + application = SharedDataMiddleware(application, static_files) + + if use_debugger: + from .debug import DebuggedApplication + + application = DebuggedApplication(application, evalex=use_evalex) + + if not is_running_from_reloader(): + s = prepare_socket(hostname, port) + fd = s.fileno() + os.environ["WERKZEUG_SERVER_FD"] = str(fd) + else: + fd = int(os.environ["WERKZEUG_SERVER_FD"]) + + srv = make_server( + hostname, + port, + application, + threaded, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + + if not is_running_from_reloader(): + srv.log_startup() + + if use_reloader: + from ._reloader import run_with_reloader + + run_with_reloader( + srv.serve_forever, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + interval=reloader_interval, + reloader_type=reloader_type, + ) + else: + srv.serve_forever() diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/test.py b/axios-example/lib/python3.10/site-packages/werkzeug/test.py new file mode 100644 index 0000000..75c5548 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/test.py @@ -0,0 +1,1325 @@ +import mimetypes +import sys +import typing as t +from collections import defaultdict +from datetime import datetime +from datetime import timedelta +from http.cookiejar import CookieJar +from io import BytesIO +from itertools import chain +from random import random +from tempfile import TemporaryFile +from time import time +from urllib.request import Request as _UrllibRequest + +from ._internal import _get_environ +from ._internal import _make_encode_wrapper +from ._internal import _wsgi_decoding_dance +from ._internal import _wsgi_encoding_dance +from .datastructures import Authorization +from .datastructures import CallbackDict +from .datastructures import CombinedMultiDict +from .datastructures import EnvironHeaders +from .datastructures import FileMultiDict +from .datastructures import Headers +from .datastructures import MultiDict +from .http import dump_cookie +from .http import dump_options_header +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartEncoder +from .sansio.multipart import Preamble +from .urls import iri_to_uri +from .urls import url_encode +from .urls import url_fix +from .urls import url_parse +from .urls import url_unparse +from .urls import url_unquote +from .utils import cached_property +from .utils import get_content_type +from .wrappers.request import Request +from .wrappers.response import Response +from .wsgi import ClosingIterator +from .wsgi import get_current_url + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def stream_encode_multipart( + data: t.Mapping[str, t.Any], + use_tempfile: bool = True, + threshold: int = 1024 * 500, + boundary: t.Optional[str] = None, + charset: str = "utf-8", +) -> t.Tuple[t.IO[bytes], int, str]: + """Encode a dict of values (either strings or file descriptors or + :class:`FileStorage` objects.) into a multipart encoded string stored + in a file descriptor. + """ + if boundary is None: + boundary = f"---------------WerkzeugFormPart_{time()}{random()}" + + stream: t.IO[bytes] = BytesIO() + total_length = 0 + on_disk = False + write_binary: t.Callable[[bytes], int] + + if use_tempfile: + + def write_binary(s: bytes) -> int: + nonlocal stream, total_length, on_disk + + if on_disk: + return stream.write(s) + else: + length = len(s) + + if length + total_length <= threshold: + stream.write(s) + else: + new_stream = t.cast(t.IO[bytes], TemporaryFile("wb+")) + new_stream.write(stream.getvalue()) # type: ignore + new_stream.write(s) + stream = new_stream + on_disk = True + + total_length += length + return length + + else: + write_binary = stream.write + + encoder = MultipartEncoder(boundary.encode()) + write_binary(encoder.send_event(Preamble(data=b""))) + for key, value in _iter_data(data): + reader = getattr(value, "read", None) + if reader is not None: + filename = getattr(value, "filename", getattr(value, "name", None)) + content_type = getattr(value, "content_type", None) + if content_type is None: + content_type = ( + filename + and mimetypes.guess_type(filename)[0] + or "application/octet-stream" + ) + headers = Headers([("Content-Type", content_type)]) + if filename is None: + write_binary(encoder.send_event(Field(name=key, headers=headers))) + else: + write_binary( + encoder.send_event( + File(name=key, filename=filename, headers=headers) + ) + ) + while True: + chunk = reader(16384) + + if not chunk: + break + + write_binary(encoder.send_event(Data(data=chunk, more_data=True))) + else: + if not isinstance(value, str): + value = str(value) + write_binary(encoder.send_event(Field(name=key, headers=Headers()))) + write_binary( + encoder.send_event(Data(data=value.encode(charset), more_data=False)) + ) + + write_binary(encoder.send_event(Epilogue(data=b""))) + + length = stream.tell() + stream.seek(0) + return stream, length, boundary + + +def encode_multipart( + values: t.Mapping[str, t.Any], + boundary: t.Optional[str] = None, + charset: str = "utf-8", +) -> t.Tuple[str, bytes]: + """Like `stream_encode_multipart` but returns a tuple in the form + (``boundary``, ``data``) where data is bytes. + """ + stream, length, boundary = stream_encode_multipart( + values, use_tempfile=False, boundary=boundary, charset=charset + ) + return boundary, stream.read() + + +class _TestCookieHeaders: + """A headers adapter for cookielib""" + + def __init__(self, headers: t.Union[Headers, t.List[t.Tuple[str, str]]]) -> None: + self.headers = headers + + def getheaders(self, name: str) -> t.Iterable[str]: + headers = [] + name = name.lower() + for k, v in self.headers: + if k.lower() == name: + headers.append(v) + return headers + + def get_all( + self, name: str, default: t.Optional[t.Iterable[str]] = None + ) -> t.Iterable[str]: + headers = self.getheaders(name) + + if not headers: + return default # type: ignore + + return headers + + +class _TestCookieResponse: + """Something that looks like a httplib.HTTPResponse, but is actually just an + adapter for our test responses to make them available for cookielib. + """ + + def __init__(self, headers: t.Union[Headers, t.List[t.Tuple[str, str]]]) -> None: + self.headers = _TestCookieHeaders(headers) + + def info(self) -> _TestCookieHeaders: + return self.headers + + +class _TestCookieJar(CookieJar): + """A cookielib.CookieJar modified to inject and read cookie headers from + and to wsgi environments, and wsgi application responses. + """ + + def inject_wsgi(self, environ: "WSGIEnvironment") -> None: + """Inject the cookies as client headers into the server's wsgi + environment. + """ + cvals = [f"{c.name}={c.value}" for c in self] + + if cvals: + environ["HTTP_COOKIE"] = "; ".join(cvals) + else: + environ.pop("HTTP_COOKIE", None) + + def extract_wsgi( + self, + environ: "WSGIEnvironment", + headers: t.Union[Headers, t.List[t.Tuple[str, str]]], + ) -> None: + """Extract the server's set-cookie headers as cookies into the + cookie jar. + """ + self.extract_cookies( + _TestCookieResponse(headers), # type: ignore + _UrllibRequest(get_current_url(environ)), + ) + + +def _iter_data(data: t.Mapping[str, t.Any]) -> t.Iterator[t.Tuple[str, t.Any]]: + """Iterate over a mapping that might have a list of values, yielding + all key, value pairs. Almost like iter_multi_items but only allows + lists, not tuples, of values so tuples can be used for files. + """ + if isinstance(data, MultiDict): + yield from data.items(multi=True) + else: + for key, value in data.items(): + if isinstance(value, list): + for v in value: + yield key, v + else: + yield key, value + + +_TAnyMultiDict = t.TypeVar("_TAnyMultiDict", bound=MultiDict) + + +class EnvironBuilder: + """This class can be used to conveniently create a WSGI environment + for testing purposes. It can be used to quickly create WSGI environments + or request objects from arbitrary data. + + The signature of this class is also used in some other places as of + Werkzeug 0.5 (:func:`create_environ`, :meth:`Response.from_values`, + :meth:`Client.open`). Because of this most of the functionality is + available through the constructor alone. + + Files and regular form data can be manipulated independently of each + other with the :attr:`form` and :attr:`files` attributes, but are + passed with the same argument to the constructor: `data`. + + `data` can be any of these values: + + - a `str` or `bytes` object: The object is converted into an + :attr:`input_stream`, the :attr:`content_length` is set and you have to + provide a :attr:`content_type`. + - a `dict` or :class:`MultiDict`: The keys have to be strings. The values + have to be either any of the following objects, or a list of any of the + following objects: + + - a :class:`file`-like object: These are converted into + :class:`FileStorage` objects automatically. + - a `tuple`: The :meth:`~FileMultiDict.add_file` method is called + with the key and the unpacked `tuple` items as positional + arguments. + - a `str`: The string is set as form data for the associated key. + - a file-like object: The object content is loaded in memory and then + handled like a regular `str` or a `bytes`. + + :param path: the path of the request. In the WSGI environment this will + end up as `PATH_INFO`. If the `query_string` is not defined + and there is a question mark in the `path` everything after + it is used as query string. + :param base_url: the base URL is a URL that is used to extract the WSGI + URL scheme, host (server name + server port) and the + script root (`SCRIPT_NAME`). + :param query_string: an optional string or dict with URL parameters. + :param method: the HTTP method to use, defaults to `GET`. + :param input_stream: an optional input stream. Do not specify this and + `data`. As soon as an input stream is set you can't + modify :attr:`args` and :attr:`files` unless you + set the :attr:`input_stream` to `None` again. + :param content_type: The content type for the request. As of 0.5 you + don't have to provide this when specifying files + and form data via `data`. + :param content_length: The content length for the request. You don't + have to specify this when providing data via + `data`. + :param errors_stream: an optional error stream that is used for + `wsgi.errors`. Defaults to :data:`stderr`. + :param multithread: controls `wsgi.multithread`. Defaults to `False`. + :param multiprocess: controls `wsgi.multiprocess`. Defaults to `False`. + :param run_once: controls `wsgi.run_once`. Defaults to `False`. + :param headers: an optional list or :class:`Headers` object of headers. + :param data: a string or dict of form data or a file-object. + See explanation above. + :param json: An object to be serialized and assigned to ``data``. + Defaults the content type to ``"application/json"``. + Serialized with the function assigned to :attr:`json_dumps`. + :param environ_base: an optional dict of environment defaults. + :param environ_overrides: an optional dict of environment overrides. + :param charset: the charset used to encode string data. + :param auth: An authorization object to use for the + ``Authorization`` header value. A ``(username, password)`` tuple + is a shortcut for ``Basic`` authorization. + + .. versionchanged:: 2.1 + ``CONTENT_TYPE`` and ``CONTENT_LENGTH`` are not duplicated as + header keys in the environ. + + .. versionchanged:: 2.0 + ``REQUEST_URI`` and ``RAW_URI`` is the full raw URI including + the query string, not only the path. + + .. versionchanged:: 2.0 + The default :attr:`request_class` is ``Request`` instead of + ``BaseRequest``. + + .. versionadded:: 2.0 + Added the ``auth`` parameter. + + .. versionadded:: 0.15 + The ``json`` param and :meth:`json_dumps` method. + + .. versionadded:: 0.15 + The environ has keys ``REQUEST_URI`` and ``RAW_URI`` containing + the path before percent-decoding. This is not part of the WSGI + PEP, but many WSGI servers include it. + + .. versionchanged:: 0.6 + ``path`` and ``base_url`` can now be unicode strings that are + encoded with :func:`iri_to_uri`. + """ + + #: the server protocol to use. defaults to HTTP/1.1 + server_protocol = "HTTP/1.1" + + #: the wsgi version to use. defaults to (1, 0) + wsgi_version = (1, 0) + + #: The default request class used by :meth:`get_request`. + request_class = Request + + import json + + #: The serialization function used when ``json`` is passed. + json_dumps = staticmethod(json.dumps) + del json + + _args: t.Optional[MultiDict] + _query_string: t.Optional[str] + _input_stream: t.Optional[t.IO[bytes]] + _form: t.Optional[MultiDict] + _files: t.Optional[FileMultiDict] + + def __init__( + self, + path: str = "/", + base_url: t.Optional[str] = None, + query_string: t.Optional[t.Union[t.Mapping[str, str], str]] = None, + method: str = "GET", + input_stream: t.Optional[t.IO[bytes]] = None, + content_type: t.Optional[str] = None, + content_length: t.Optional[int] = None, + errors_stream: t.Optional[t.IO[str]] = None, + multithread: bool = False, + multiprocess: bool = False, + run_once: bool = False, + headers: t.Optional[t.Union[Headers, t.Iterable[t.Tuple[str, str]]]] = None, + data: t.Optional[ + t.Union[t.IO[bytes], str, bytes, t.Mapping[str, t.Any]] + ] = None, + environ_base: t.Optional[t.Mapping[str, t.Any]] = None, + environ_overrides: t.Optional[t.Mapping[str, t.Any]] = None, + charset: str = "utf-8", + mimetype: t.Optional[str] = None, + json: t.Optional[t.Mapping[str, t.Any]] = None, + auth: t.Optional[t.Union[Authorization, t.Tuple[str, str]]] = None, + ) -> None: + path_s = _make_encode_wrapper(path) + if query_string is not None and path_s("?") in path: + raise ValueError("Query string is defined in the path and as an argument") + request_uri = url_parse(path) + if query_string is None and path_s("?") in path: + query_string = request_uri.query + self.charset = charset + self.path = iri_to_uri(request_uri.path) + self.request_uri = path + if base_url is not None: + base_url = url_fix(iri_to_uri(base_url, charset), charset) + self.base_url = base_url # type: ignore + if isinstance(query_string, (bytes, str)): + self.query_string = query_string + else: + if query_string is None: + query_string = MultiDict() + elif not isinstance(query_string, MultiDict): + query_string = MultiDict(query_string) + self.args = query_string + self.method = method + if headers is None: + headers = Headers() + elif not isinstance(headers, Headers): + headers = Headers(headers) + self.headers = headers + if content_type is not None: + self.content_type = content_type + if errors_stream is None: + errors_stream = sys.stderr + self.errors_stream = errors_stream + self.multithread = multithread + self.multiprocess = multiprocess + self.run_once = run_once + self.environ_base = environ_base + self.environ_overrides = environ_overrides + self.input_stream = input_stream + self.content_length = content_length + self.closed = False + + if auth is not None: + if isinstance(auth, tuple): + auth = Authorization( + "basic", {"username": auth[0], "password": auth[1]} + ) + + self.headers.set("Authorization", auth.to_header()) + + if json is not None: + if data is not None: + raise TypeError("can't provide both json and data") + + data = self.json_dumps(json) + + if self.content_type is None: + self.content_type = "application/json" + + if data: + if input_stream is not None: + raise TypeError("can't provide input stream and data") + if hasattr(data, "read"): + data = data.read() # type: ignore + if isinstance(data, str): + data = data.encode(self.charset) + if isinstance(data, bytes): + self.input_stream = BytesIO(data) + if self.content_length is None: + self.content_length = len(data) + else: + for key, value in _iter_data(data): # type: ignore + if isinstance(value, (tuple, dict)) or hasattr(value, "read"): + self._add_file_from_data(key, value) + else: + self.form.setlistdefault(key).append(value) + + if mimetype is not None: + self.mimetype = mimetype + + @classmethod + def from_environ( + cls, environ: "WSGIEnvironment", **kwargs: t.Any + ) -> "EnvironBuilder": + """Turn an environ dict back into a builder. Any extra kwargs + override the args extracted from the environ. + + .. versionchanged:: 2.0 + Path and query values are passed through the WSGI decoding + dance to avoid double encoding. + + .. versionadded:: 0.15 + """ + headers = Headers(EnvironHeaders(environ)) + out = { + "path": _wsgi_decoding_dance(environ["PATH_INFO"]), + "base_url": cls._make_base_url( + environ["wsgi.url_scheme"], + headers.pop("Host"), + _wsgi_decoding_dance(environ["SCRIPT_NAME"]), + ), + "query_string": _wsgi_decoding_dance(environ["QUERY_STRING"]), + "method": environ["REQUEST_METHOD"], + "input_stream": environ["wsgi.input"], + "content_type": headers.pop("Content-Type", None), + "content_length": headers.pop("Content-Length", None), + "errors_stream": environ["wsgi.errors"], + "multithread": environ["wsgi.multithread"], + "multiprocess": environ["wsgi.multiprocess"], + "run_once": environ["wsgi.run_once"], + "headers": headers, + } + out.update(kwargs) + return cls(**out) + + def _add_file_from_data( + self, + key: str, + value: t.Union[ + t.IO[bytes], t.Tuple[t.IO[bytes], str], t.Tuple[t.IO[bytes], str, str] + ], + ) -> None: + """Called in the EnvironBuilder to add files from the data dict.""" + if isinstance(value, tuple): + self.files.add_file(key, *value) + else: + self.files.add_file(key, value) + + @staticmethod + def _make_base_url(scheme: str, host: str, script_root: str) -> str: + return url_unparse((scheme, host, script_root, "", "")).rstrip("/") + "/" + + @property + def base_url(self) -> str: + """The base URL is used to extract the URL scheme, host name, + port, and root path. + """ + return self._make_base_url(self.url_scheme, self.host, self.script_root) + + @base_url.setter + def base_url(self, value: t.Optional[str]) -> None: + if value is None: + scheme = "http" + netloc = "localhost" + script_root = "" + else: + scheme, netloc, script_root, qs, anchor = url_parse(value) + if qs or anchor: + raise ValueError("base url must not contain a query string or fragment") + self.script_root = script_root.rstrip("/") + self.host = netloc + self.url_scheme = scheme + + @property + def content_type(self) -> t.Optional[str]: + """The content type for the request. Reflected from and to + the :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + ct = self.headers.get("Content-Type") + if ct is None and not self._input_stream: + if self._files: + return "multipart/form-data" + if self._form: + return "application/x-www-form-urlencoded" + return None + return ct + + @content_type.setter + def content_type(self, value: t.Optional[str]) -> None: + if value is None: + self.headers.pop("Content-Type", None) + else: + self.headers["Content-Type"] = value + + @property + def mimetype(self) -> t.Optional[str]: + """The mimetype (content type without charset etc.) + + .. versionadded:: 0.14 + """ + ct = self.content_type + return ct.split(";")[0].strip() if ct else None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.content_type = get_content_type(value, self.charset) + + @property + def mimetype_params(self) -> t.Mapping[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.14 + """ + + def on_update(d: CallbackDict) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + @property + def content_length(self) -> t.Optional[int]: + """The content length as integer. Reflected from and to the + :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + return self.headers.get("Content-Length", type=int) + + @content_length.setter + def content_length(self, value: t.Optional[int]) -> None: + if value is None: + self.headers.pop("Content-Length", None) + else: + self.headers["Content-Length"] = str(value) + + def _get_form(self, name: str, storage: t.Type[_TAnyMultiDict]) -> _TAnyMultiDict: + """Common behavior for getting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param storage: Storage class used for the data. + """ + if self.input_stream is not None: + raise AttributeError("an input stream is defined") + + rv = getattr(self, name) + + if rv is None: + rv = storage() + setattr(self, name, rv) + + return rv # type: ignore + + def _set_form(self, name: str, value: MultiDict) -> None: + """Common behavior for setting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param value: Value to assign to the attribute. + """ + self._input_stream = None + setattr(self, name, value) + + @property + def form(self) -> MultiDict: + """A :class:`MultiDict` of form values.""" + return self._get_form("_form", MultiDict) + + @form.setter + def form(self, value: MultiDict) -> None: + self._set_form("_form", value) + + @property + def files(self) -> FileMultiDict: + """A :class:`FileMultiDict` of uploaded files. Use + :meth:`~FileMultiDict.add_file` to add new files. + """ + return self._get_form("_files", FileMultiDict) + + @files.setter + def files(self, value: FileMultiDict) -> None: + self._set_form("_files", value) + + @property + def input_stream(self) -> t.Optional[t.IO[bytes]]: + """An optional input stream. This is mutually exclusive with + setting :attr:`form` and :attr:`files`, setting it will clear + those. Do not provide this if the method is not ``POST`` or + another method that has a body. + """ + return self._input_stream + + @input_stream.setter + def input_stream(self, value: t.Optional[t.IO[bytes]]) -> None: + self._input_stream = value + self._form = None + self._files = None + + @property + def query_string(self) -> str: + """The query string. If you set this to a string + :attr:`args` will no longer be available. + """ + if self._query_string is None: + if self._args is not None: + return url_encode(self._args, charset=self.charset) + return "" + return self._query_string + + @query_string.setter + def query_string(self, value: t.Optional[str]) -> None: + self._query_string = value + self._args = None + + @property + def args(self) -> MultiDict: + """The URL arguments as :class:`MultiDict`.""" + if self._query_string is not None: + raise AttributeError("a query string is defined") + if self._args is None: + self._args = MultiDict() + return self._args + + @args.setter + def args(self, value: t.Optional[MultiDict]) -> None: + self._query_string = None + self._args = value + + @property + def server_name(self) -> str: + """The server name (read-only, use :attr:`host` to set)""" + return self.host.split(":", 1)[0] + + @property + def server_port(self) -> int: + """The server port as integer (read-only, use :attr:`host` to set)""" + pieces = self.host.split(":", 1) + if len(pieces) == 2 and pieces[1].isdigit(): + return int(pieces[1]) + if self.url_scheme == "https": + return 443 + return 80 + + def __del__(self) -> None: + try: + self.close() + except Exception: + pass + + def close(self) -> None: + """Closes all files. If you put real :class:`file` objects into the + :attr:`files` dict you can call this method to automatically close + them all in one go. + """ + if self.closed: + return + try: + files = self.files.values() + except AttributeError: + files = () # type: ignore + for f in files: + try: + f.close() + except Exception: + pass + self.closed = True + + def get_environ(self) -> "WSGIEnvironment": + """Return the built environ. + + .. versionchanged:: 0.15 + The content type and length headers are set based on + input stream detection. Previously this only set the WSGI + keys. + """ + input_stream = self.input_stream + content_length = self.content_length + + mimetype = self.mimetype + content_type = self.content_type + + if input_stream is not None: + start_pos = input_stream.tell() + input_stream.seek(0, 2) + end_pos = input_stream.tell() + input_stream.seek(start_pos) + content_length = end_pos - start_pos + elif mimetype == "multipart/form-data": + input_stream, content_length, boundary = stream_encode_multipart( + CombinedMultiDict([self.form, self.files]), charset=self.charset + ) + content_type = f'{mimetype}; boundary="{boundary}"' + elif mimetype == "application/x-www-form-urlencoded": + form_encoded = url_encode(self.form, charset=self.charset).encode("ascii") + content_length = len(form_encoded) + input_stream = BytesIO(form_encoded) + else: + input_stream = BytesIO() + + result: "WSGIEnvironment" = {} + if self.environ_base: + result.update(self.environ_base) + + def _path_encode(x: str) -> str: + return _wsgi_encoding_dance(url_unquote(x, self.charset), self.charset) + + raw_uri = _wsgi_encoding_dance(self.request_uri, self.charset) + result.update( + { + "REQUEST_METHOD": self.method, + "SCRIPT_NAME": _path_encode(self.script_root), + "PATH_INFO": _path_encode(self.path), + "QUERY_STRING": _wsgi_encoding_dance(self.query_string, self.charset), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": raw_uri, + # Non-standard, added by gunicorn + "RAW_URI": raw_uri, + "SERVER_NAME": self.server_name, + "SERVER_PORT": str(self.server_port), + "HTTP_HOST": self.host, + "SERVER_PROTOCOL": self.server_protocol, + "wsgi.version": self.wsgi_version, + "wsgi.url_scheme": self.url_scheme, + "wsgi.input": input_stream, + "wsgi.errors": self.errors_stream, + "wsgi.multithread": self.multithread, + "wsgi.multiprocess": self.multiprocess, + "wsgi.run_once": self.run_once, + } + ) + + headers = self.headers.copy() + # Don't send these as headers, they're part of the environ. + headers.remove("Content-Type") + headers.remove("Content-Length") + + if content_type is not None: + result["CONTENT_TYPE"] = content_type + + if content_length is not None: + result["CONTENT_LENGTH"] = str(content_length) + + combined_headers = defaultdict(list) + + for key, value in headers.to_wsgi_list(): + combined_headers[f"HTTP_{key.upper().replace('-', '_')}"].append(value) + + for key, values in combined_headers.items(): + result[key] = ", ".join(values) + + if self.environ_overrides: + result.update(self.environ_overrides) + + return result + + def get_request(self, cls: t.Optional[t.Type[Request]] = None) -> Request: + """Returns a request with the data. If the request class is not + specified :attr:`request_class` is used. + + :param cls: The request wrapper to use. + """ + if cls is None: + cls = self.request_class + + return cls(self.get_environ()) + + +class ClientRedirectError(Exception): + """If a redirect loop is detected when using follow_redirects=True with + the :cls:`Client`, then this exception is raised. + """ + + +class Client: + """This class allows you to send requests to a wrapped application. + + The use_cookies parameter indicates whether cookies should be stored and + sent for subsequent requests. This is True by default, but passing False + will disable this behaviour. + + If you want to request some subdomain of your application you may set + `allow_subdomain_redirects` to `True` as if not no external redirects + are allowed. + + .. versionchanged:: 2.1 + Removed deprecated behavior of treating the response as a + tuple. All data is available as properties on the returned + response object. + + .. versionchanged:: 2.0 + ``response_wrapper`` is always a subclass of + :class:``TestResponse``. + + .. versionchanged:: 0.5 + Added the ``use_cookies`` parameter. + """ + + def __init__( + self, + application: "WSGIApplication", + response_wrapper: t.Optional[t.Type["Response"]] = None, + use_cookies: bool = True, + allow_subdomain_redirects: bool = False, + ) -> None: + self.application = application + + if response_wrapper in {None, Response}: + response_wrapper = TestResponse + elif not isinstance(response_wrapper, TestResponse): + response_wrapper = type( + "WrapperTestResponse", + (TestResponse, response_wrapper), # type: ignore + {}, + ) + + self.response_wrapper = t.cast(t.Type["TestResponse"], response_wrapper) + + if use_cookies: + self.cookie_jar: t.Optional[_TestCookieJar] = _TestCookieJar() + else: + self.cookie_jar = None + + self.allow_subdomain_redirects = allow_subdomain_redirects + + def set_cookie( + self, + server_name: str, + key: str, + value: str = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + charset: str = "utf-8", + ) -> None: + """Sets a cookie in the client's cookie jar. The server name + is required and has to match the one that is also passed to + the open call. + """ + assert self.cookie_jar is not None, "cookies disabled" + header = dump_cookie( + key, + value, + max_age, + expires, + path, + domain, + secure, + httponly, + charset, + samesite=samesite, + ) + environ = create_environ(path, base_url=f"http://{server_name}") + headers = [("Set-Cookie", header)] + self.cookie_jar.extract_wsgi(environ, headers) + + def delete_cookie( + self, + server_name: str, + key: str, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Deletes a cookie in the test client.""" + self.set_cookie( + server_name, + key, + expires=0, + max_age=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + def run_wsgi_app( + self, environ: "WSGIEnvironment", buffered: bool = False + ) -> t.Tuple[t.Iterable[bytes], str, Headers]: + """Runs the wrapped WSGI app with the given environment. + + :meta private: + """ + if self.cookie_jar is not None: + self.cookie_jar.inject_wsgi(environ) + + rv = run_wsgi_app(self.application, environ, buffered=buffered) + + if self.cookie_jar is not None: + self.cookie_jar.extract_wsgi(environ, rv[2]) + + return rv + + def resolve_redirect( + self, response: "TestResponse", buffered: bool = False + ) -> "TestResponse": + """Perform a new request to the location given by the redirect + response to the previous request. + + :meta private: + """ + scheme, netloc, path, qs, anchor = url_parse(response.location) + builder = EnvironBuilder.from_environ( + response.request.environ, path=path, query_string=qs + ) + + to_name_parts = netloc.split(":", 1)[0].split(".") + from_name_parts = builder.server_name.split(".") + + if to_name_parts != [""]: + # The new location has a host, use it for the base URL. + builder.url_scheme = scheme + builder.host = netloc + else: + # A local redirect with autocorrect_location_header=False + # doesn't have a host, so use the request's host. + to_name_parts = from_name_parts + + # Explain why a redirect to a different server name won't be followed. + if to_name_parts != from_name_parts: + if to_name_parts[-len(from_name_parts) :] == from_name_parts: + if not self.allow_subdomain_redirects: + raise RuntimeError("Following subdomain redirects is not enabled.") + else: + raise RuntimeError("Following external redirects is not supported.") + + path_parts = path.split("/") + root_parts = builder.script_root.split("/") + + if path_parts[: len(root_parts)] == root_parts: + # Strip the script root from the path. + builder.path = path[len(builder.script_root) :] + else: + # The new location is not under the script root, so use the + # whole path and clear the previous root. + builder.path = path + builder.script_root = "" + + # Only 307 and 308 preserve all of the original request. + if response.status_code not in {307, 308}: + # HEAD is preserved, everything else becomes GET. + if builder.method != "HEAD": + builder.method = "GET" + + # Clear the body and the headers that describe it. + + if builder.input_stream is not None: + builder.input_stream.close() + builder.input_stream = None + + builder.content_type = None + builder.content_length = None + builder.headers.pop("Transfer-Encoding", None) + + return self.open(builder, buffered=buffered) + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> "TestResponse": + """Generate an environ dict from the given arguments, make a + request to the application using it, and return the response. + + :param args: Passed to :class:`EnvironBuilder` to create the + environ for the request. If a single arg is passed, it can + be an existing :class:`EnvironBuilder` or an environ dict. + :param buffered: Convert the iterator returned by the app into + a list. If the iterator has a ``close()`` method, it is + called automatically. + :param follow_redirects: Make additional requests to follow HTTP + redirects until a non-redirect status is returned. + :attr:`TestResponse.history` lists the intermediate + responses. + + .. versionchanged:: 2.1 + Removed the ``as_tuple`` parameter. + + .. versionchanged:: 2.0 + ``as_tuple`` is deprecated and will be removed in Werkzeug + 2.1. Use :attr:`TestResponse.request` and + ``request.environ`` instead. + + .. versionchanged:: 2.0 + The request input stream is closed when calling + ``response.close()``. Input streams for redirects are + automatically closed. + + .. versionchanged:: 0.5 + If a dict is provided as file in the dict for the ``data`` + parameter the content type has to be called ``content_type`` + instead of ``mimetype``. This change was made for + consistency with :class:`werkzeug.FileWrapper`. + + .. versionchanged:: 0.5 + Added the ``follow_redirects`` parameter. + """ + request: t.Optional["Request"] = None + + if not kwargs and len(args) == 1: + arg = args[0] + + if isinstance(arg, EnvironBuilder): + request = arg.get_request() + elif isinstance(arg, dict): + request = EnvironBuilder.from_environ(arg).get_request() + elif isinstance(arg, Request): + request = arg + + if request is None: + builder = EnvironBuilder(*args, **kwargs) + + try: + request = builder.get_request() + finally: + builder.close() + + response = self.run_wsgi_app(request.environ, buffered=buffered) + response = self.response_wrapper(*response, request=request) + + redirects = set() + history: t.List["TestResponse"] = [] + + if not follow_redirects: + return response + + while response.status_code in { + 301, + 302, + 303, + 305, + 307, + 308, + }: + # Exhaust intermediate response bodies to ensure middleware + # that returns an iterator runs any cleanup code. + if not buffered: + response.make_sequence() + response.close() + + new_redirect_entry = (response.location, response.status_code) + + if new_redirect_entry in redirects: + raise ClientRedirectError( + f"Loop detected: A {response.status_code} redirect" + f" to {response.location} was already made." + ) + + redirects.add(new_redirect_entry) + response.history = tuple(history) + history.append(response) + response = self.resolve_redirect(response, buffered=buffered) + else: + # This is the final request after redirects. + response.history = tuple(history) + # Close the input stream when closing the response, in case + # the input is an open temporary file. + response.call_on_close(request.input_stream.close) + return response + + def get(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``GET``.""" + kw["method"] = "GET" + return self.open(*args, **kw) + + def post(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``POST``.""" + kw["method"] = "POST" + return self.open(*args, **kw) + + def put(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``PUT``.""" + kw["method"] = "PUT" + return self.open(*args, **kw) + + def delete(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``DELETE``.""" + kw["method"] = "DELETE" + return self.open(*args, **kw) + + def patch(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``PATCH``.""" + kw["method"] = "PATCH" + return self.open(*args, **kw) + + def options(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``OPTIONS``.""" + kw["method"] = "OPTIONS" + return self.open(*args, **kw) + + def head(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``HEAD``.""" + kw["method"] = "HEAD" + return self.open(*args, **kw) + + def trace(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``TRACE``.""" + kw["method"] = "TRACE" + return self.open(*args, **kw) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.application!r}>" + + +def create_environ(*args: t.Any, **kwargs: t.Any) -> "WSGIEnvironment": + """Create a new WSGI environ dict based on the values passed. The first + parameter should be the path of the request which defaults to '/'. The + second one can either be an absolute path (in that case the host is + localhost:80) or a full path to the request with scheme, netloc port and + the path to the script. + + This accepts the same arguments as the :class:`EnvironBuilder` + constructor. + + .. versionchanged:: 0.5 + This function is now a thin wrapper over :class:`EnvironBuilder` which + was added in 0.5. The `headers`, `environ_base`, `environ_overrides` + and `charset` parameters were added. + """ + builder = EnvironBuilder(*args, **kwargs) + + try: + return builder.get_environ() + finally: + builder.close() + + +def run_wsgi_app( + app: "WSGIApplication", environ: "WSGIEnvironment", buffered: bool = False +) -> t.Tuple[t.Iterable[bytes], str, Headers]: + """Return a tuple in the form (app_iter, status, headers) of the + application output. This works best if you pass it an application that + returns an iterator all the time. + + Sometimes applications may use the `write()` callable returned + by the `start_response` function. This tries to resolve such edge + cases automatically. But if you don't get the expected output you + should set `buffered` to `True` which enforces buffering. + + If passed an invalid WSGI application the behavior of this function is + undefined. Never pass non-conforming WSGI applications to this function. + + :param app: the application to execute. + :param buffered: set to `True` to enforce buffering. + :return: tuple in the form ``(app_iter, status, headers)`` + """ + # Copy environ to ensure any mutations by the app (ProxyFix, for + # example) don't affect subsequent requests (such as redirects). + environ = _get_environ(environ).copy() + status: str + response: t.Optional[t.Tuple[str, t.List[t.Tuple[str, str]]]] = None + buffer: t.List[bytes] = [] + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal response + + if exc_info: + try: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + + response = (status, headers) + return buffer.append + + app_rv = app(environ, start_response) + close_func = getattr(app_rv, "close", None) + app_iter: t.Iterable[bytes] = iter(app_rv) + + # when buffering we emit the close call early and convert the + # application iterator into a regular list + if buffered: + try: + app_iter = list(app_iter) + finally: + if close_func is not None: + close_func() + + # otherwise we iterate the application iter until we have a response, chain + # the already received data with the already collected data and wrap it in + # a new `ClosingIterator` if we need to restore a `close` callable from the + # original return value. + else: + for item in app_iter: + buffer.append(item) + + if response is not None: + break + + if buffer: + app_iter = chain(buffer, app_iter) + + if close_func is not None and app_iter is not app_rv: + app_iter = ClosingIterator(app_iter, close_func) + + status, headers = response # type: ignore + return app_iter, status, Headers(headers) + + +class TestResponse(Response): + """:class:`~werkzeug.wrappers.Response` subclass that provides extra + information about requests made with the test :class:`Client`. + + Test client requests will always return an instance of this class. + If a custom response class is passed to the client, it is + subclassed along with this to support test information. + + If the test request included large files, or if the application is + serving a file, call :meth:`close` to close any open files and + prevent Python showing a ``ResourceWarning``. + + .. versionchanged:: 2.1 + Removed deprecated behavior for treating the response instance + as a tuple. + + .. versionadded:: 2.0 + Test client methods always return instances of this class. + """ + + request: Request + """A request object with the environ used to make the request that + resulted in this response. + """ + + history: t.Tuple["TestResponse", ...] + """A list of intermediate responses. Populated when the test request + is made with ``follow_redirects`` enabled. + """ + + # Tell Pytest to ignore this, it's not a test class. + __test__ = False + + def __init__( + self, + response: t.Iterable[bytes], + status: str, + headers: Headers, + request: Request, + history: t.Tuple["TestResponse"] = (), # type: ignore + **kwargs: t.Any, + ) -> None: + super().__init__(response, status, headers, **kwargs) + self.request = request + self.history = history + self._compat_tuple = response, status, headers + + @cached_property + def text(self) -> str: + """The response data as text. A shortcut for + ``response.get_data(as_text=True)``. + + .. versionadded:: 2.1 + """ + return self.get_data(as_text=True) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/testapp.py b/axios-example/lib/python3.10/site-packages/werkzeug/testapp.py new file mode 100644 index 0000000..0829e33 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/testapp.py @@ -0,0 +1,240 @@ +"""A small application that can be used to test a WSGI server and check +it for WSGI compliance. +""" +import base64 +import os +import sys +import typing as t +from html import escape +from textwrap import wrap + +from . import __version__ as _werkzeug_version +from .wrappers.request import Request +from .wrappers.response import Response + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + + +logo = Response( + base64.b64decode( + """ +R0lGODlhoACgAOMIAAEDACwpAEpCAGdgAJaKAM28AOnVAP3rAP///////// +//////////////////////yH5BAEKAAgALAAAAACgAKAAAAT+EMlJq704680R+F0ojmRpnuj0rWnrv +nB8rbRs33gu0bzu/0AObxgsGn3D5HHJbCUFyqZ0ukkSDlAidctNFg7gbI9LZlrBaHGtzAae0eloe25 +7w9EDOX2fst/xenyCIn5/gFqDiVVDV4aGeYiKkhSFjnCQY5OTlZaXgZp8nJ2ekaB0SQOjqphrpnOiq +ncEn65UsLGytLVmQ6m4sQazpbtLqL/HwpnER8bHyLrLOc3Oz8PRONPU1crXN9na263dMt/g4SzjMeX +m5yDpLqgG7OzJ4u8lT/P69ej3JPn69kHzN2OIAHkB9RUYSFCFQYQJFTIkCDBiwoXWGnowaLEjRm7+G +p9A7Hhx4rUkAUaSLJlxHMqVMD/aSycSZkyTplCqtGnRAM5NQ1Ly5OmzZc6gO4d6DGAUKA+hSocWYAo +SlM6oUWX2O/o0KdaVU5vuSQLAa0ADwQgMEMB2AIECZhVSnTno6spgbtXmHcBUrQACcc2FrTrWS8wAf +78cMFBgwIBgbN+qvTt3ayikRBk7BoyGAGABAdYyfdzRQGV3l4coxrqQ84GpUBmrdR3xNIDUPAKDBSA +ADIGDhhqTZIWaDcrVX8EsbNzbkvCOxG8bN5w8ly9H8jyTJHC6DFndQydbguh2e/ctZJFXRxMAqqPVA +tQH5E64SPr1f0zz7sQYjAHg0In+JQ11+N2B0XXBeeYZgBZFx4tqBToiTCPv0YBgQv8JqA6BEf6RhXx +w1ENhRBnWV8ctEX4Ul2zc3aVGcQNC2KElyTDYyYUWvShdjDyMOGMuFjqnII45aogPhz/CodUHFwaDx +lTgsaOjNyhGWJQd+lFoAGk8ObghI0kawg+EV5blH3dr+digkYuAGSaQZFHFz2P/cTaLmhF52QeSb45 +Jwxd+uSVGHlqOZpOeJpCFZ5J+rkAkFjQ0N1tah7JJSZUFNsrkeJUJMIBi8jyaEKIhKPomnC91Uo+NB +yyaJ5umnnpInIFh4t6ZSpGaAVmizqjpByDegYl8tPE0phCYrhcMWSv+uAqHfgH88ak5UXZmlKLVJhd +dj78s1Fxnzo6yUCrV6rrDOkluG+QzCAUTbCwf9SrmMLzK6p+OPHx7DF+bsfMRq7Ec61Av9i6GLw23r +idnZ+/OO0a99pbIrJkproCQMA17OPG6suq3cca5ruDfXCCDoS7BEdvmJn5otdqscn+uogRHHXs8cbh +EIfYaDY1AkrC0cqwcZpnM6ludx72x0p7Fo/hZAcpJDjax0UdHavMKAbiKltMWCF3xxh9k25N/Viud8 +ba78iCvUkt+V6BpwMlErmcgc502x+u1nSxJSJP9Mi52awD1V4yB/QHONsnU3L+A/zR4VL/indx/y64 +gqcj+qgTeweM86f0Qy1QVbvmWH1D9h+alqg254QD8HJXHvjQaGOqEqC22M54PcftZVKVSQG9jhkv7C +JyTyDoAJfPdu8v7DRZAxsP/ky9MJ3OL36DJfCFPASC3/aXlfLOOON9vGZZHydGf8LnxYJuuVIbl83y +Az5n/RPz07E+9+zw2A2ahz4HxHo9Kt79HTMx1Q7ma7zAzHgHqYH0SoZWyTuOLMiHwSfZDAQTn0ajk9 +YQqodnUYjByQZhZak9Wu4gYQsMyEpIOAOQKze8CmEF45KuAHTvIDOfHJNipwoHMuGHBnJElUoDmAyX +c2Qm/R8Ah/iILCCJOEokGowdhDYc/yoL+vpRGwyVSCWFYZNljkhEirGXsalWcAgOdeAdoXcktF2udb +qbUhjWyMQxYO01o6KYKOr6iK3fE4MaS+DsvBsGOBaMb0Y6IxADaJhFICaOLmiWTlDAnY1KzDG4ambL +cWBA8mUzjJsN2KjSaSXGqMCVXYpYkj33mcIApyhQf6YqgeNAmNvuC0t4CsDbSshZJkCS1eNisKqlyG +cF8G2JeiDX6tO6Mv0SmjCa3MFb0bJaGPMU0X7c8XcpvMaOQmCajwSeY9G0WqbBmKv34DsMIEztU6Y2 +KiDlFdt6jnCSqx7Dmt6XnqSKaFFHNO5+FmODxMCWBEaco77lNDGXBM0ECYB/+s7nKFdwSF5hgXumQe +EZ7amRg39RHy3zIjyRCykQh8Zo2iviRKyTDn/zx6EefptJj2Cw+Ep2FSc01U5ry4KLPYsTyWnVGnvb +UpyGlhjBUljyjHhWpf8OFaXwhp9O4T1gU9UeyPPa8A2l0p1kNqPXEVRm1AOs1oAGZU596t6SOR2mcB +Oco1srWtkaVrMUzIErrKri85keKqRQYX9VX0/eAUK1hrSu6HMEX3Qh2sCh0q0D2CtnUqS4hj62sE/z +aDs2Sg7MBS6xnQeooc2R2tC9YrKpEi9pLXfYXp20tDCpSP8rKlrD4axprb9u1Df5hSbz9QU0cRpfgn +kiIzwKucd0wsEHlLpe5yHXuc6FrNelOl7pY2+11kTWx7VpRu97dXA3DO1vbkhcb4zyvERYajQgAADs +=""" + ), + mimetype="image/png", +) + + +TEMPLATE = """\ + + +WSGI Information + +
    + +

    WSGI Information

    +

    + This page displays all available information about the WSGI server and + the underlying Python interpreter. +

    Python Interpreter

    + + + + + + +
    Python Version + %(python_version)s +
    Platform + %(platform)s [%(os)s] +
    API Version + %(api_version)s +
    Byteorder + %(byteorder)s +
    Werkzeug Version + %(werkzeug_version)s +
    +

    WSGI Environment

    + %(wsgi_env)s
    +

    Installed Eggs

    +

    + The following python packages were installed on the system as + Python eggs: +

      %(python_eggs)s
    +

    System Path

    +

    + The following paths are the current contents of the load path. The + following entries are looked up for Python packages. Note that not + all items in this path are folders. Gray and underlined items are + entries pointing to invalid resources or used by custom import hooks + such as the zip importer. +

    + Items with a bright background were expanded for display from a relative + path. If you encounter such paths in the output you might want to check + your setup as relative paths are usually problematic in multithreaded + environments. +

      %(sys_path)s
    +
    +""" + + +def iter_sys_path() -> t.Iterator[t.Tuple[str, bool, bool]]: + if os.name == "posix": + + def strip(x: str) -> str: + prefix = os.path.expanduser("~") + if x.startswith(prefix): + x = f"~{x[len(prefix) :]}" + return x + + else: + + def strip(x: str) -> str: + return x + + cwd = os.path.abspath(os.getcwd()) + for item in sys.path: + path = os.path.join(cwd, item or os.path.curdir) + yield strip(os.path.normpath(path)), not os.path.isdir(path), path != item + + +def render_testapp(req: Request) -> bytes: + try: + import pkg_resources + except ImportError: + eggs: t.Iterable[t.Any] = () + else: + eggs = sorted( + pkg_resources.working_set, + key=lambda x: x.project_name.lower(), # type: ignore + ) + python_eggs = [] + for egg in eggs: + try: + version = egg.version + except (ValueError, AttributeError): + version = "unknown" + python_eggs.append( + f"
  • {escape(egg.project_name)} [{escape(version)}]" + ) + + wsgi_env = [] + sorted_environ = sorted(req.environ.items(), key=lambda x: repr(x[0]).lower()) + for key, value in sorted_environ: + value = "".join(wrap(escape(repr(value)))) + wsgi_env.append(f"{escape(str(key))}{value}") + + sys_path = [] + for item, virtual, expanded in iter_sys_path(): + class_ = [] + if virtual: + class_.append("virtual") + if expanded: + class_.append("exp") + class_ = f' class="{" ".join(class_)}"' if class_ else "" + sys_path.append(f"{escape(item)}") + + return ( + TEMPLATE + % { + "python_version": "
    ".join(escape(sys.version).splitlines()), + "platform": escape(sys.platform), + "os": escape(os.name), + "api_version": sys.api_version, + "byteorder": sys.byteorder, + "werkzeug_version": _werkzeug_version, + "python_eggs": "\n".join(python_eggs), + "wsgi_env": "\n".join(wsgi_env), + "sys_path": "\n".join(sys_path), + } + ).encode("utf-8") + + +def test_app( + environ: "WSGIEnvironment", start_response: "StartResponse" +) -> t.Iterable[bytes]: + """Simple test application that dumps the environment. You can use + it to check if Werkzeug is working properly: + + .. sourcecode:: pycon + + >>> from werkzeug.serving import run_simple + >>> from werkzeug.testapp import test_app + >>> run_simple('localhost', 3000, test_app) + * Running on http://localhost:3000/ + + The application displays important information from the WSGI environment, + the Python interpreter and the installed libraries. + """ + req = Request(environ, populate_request=False) + if req.args.get("resource") == "logo": + response = logo + else: + response = Response(render_testapp(req), mimetype="text/html") + return response(environ, start_response) + + +if __name__ == "__main__": + from .serving import run_simple + + run_simple("localhost", 5000, test_app, use_reloader=True) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/urls.py b/axios-example/lib/python3.10/site-packages/werkzeug/urls.py new file mode 100644 index 0000000..67c08b0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/urls.py @@ -0,0 +1,1067 @@ +"""Functions for working with URLs. + +Contains implementations of functions from :mod:`urllib.parse` that +handle bytes and strings. +""" +import codecs +import os +import re +import typing as t + +from ._internal import _check_str_tuple +from ._internal import _decode_idna +from ._internal import _encode_idna +from ._internal import _make_encode_wrapper +from ._internal import _to_str + +if t.TYPE_CHECKING: + from . import datastructures as ds + +# A regular expression for what a valid schema looks like +_scheme_re = re.compile(r"^[a-zA-Z0-9+-.]+$") + +# Characters that are safe in any part of an URL. +_always_safe = frozenset( + bytearray( + b"abcdefghijklmnopqrstuvwxyz" + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + b"0123456789" + b"-._~" + b"$!'()*+,;" # RFC3986 sub-delims set, not including query string delimiters &= + ) +) + +_hexdigits = "0123456789ABCDEFabcdef" +_hextobyte = { + f"{a}{b}".encode("ascii"): int(f"{a}{b}", 16) + for a in _hexdigits + for b in _hexdigits +} +_bytetohex = [f"%{char:02X}".encode("ascii") for char in range(256)] + + +class _URLTuple(t.NamedTuple): + scheme: str + netloc: str + path: str + query: str + fragment: str + + +class BaseURL(_URLTuple): + """Superclass of :py:class:`URL` and :py:class:`BytesURL`.""" + + __slots__ = () + _at: str + _colon: str + _lbracket: str + _rbracket: str + + def __str__(self) -> str: + return self.to_url() + + def replace(self, **kwargs: t.Any) -> "BaseURL": + """Return an URL with the same values, except for those parameters + given new values by whichever keyword arguments are specified.""" + return self._replace(**kwargs) + + @property + def host(self) -> t.Optional[str]: + """The host part of the URL if available, otherwise `None`. The + host is either the hostname or the IP address mentioned in the + URL. It will not contain the port. + """ + return self._split_host()[0] + + @property + def ascii_host(self) -> t.Optional[str]: + """Works exactly like :attr:`host` but will return a result that + is restricted to ASCII. If it finds a netloc that is not ASCII + it will attempt to idna decode it. This is useful for socket + operations when the URL might include internationalized characters. + """ + rv = self.host + if rv is not None and isinstance(rv, str): + try: + rv = _encode_idna(rv) # type: ignore + except UnicodeError: + rv = rv.encode("ascii", "ignore") # type: ignore + return _to_str(rv, "ascii", "ignore") + + @property + def port(self) -> t.Optional[int]: + """The port in the URL as an integer if it was present, `None` + otherwise. This does not fill in default ports. + """ + try: + rv = int(_to_str(self._split_host()[1])) + if 0 <= rv <= 65535: + return rv + except (ValueError, TypeError): + pass + return None + + @property + def auth(self) -> t.Optional[str]: + """The authentication part in the URL if available, `None` + otherwise. + """ + return self._split_netloc()[0] + + @property + def username(self) -> t.Optional[str]: + """The username if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a string. + """ + rv = self._split_auth()[0] + if rv is not None: + return _url_unquote_legacy(rv) + return None + + @property + def raw_username(self) -> t.Optional[str]: + """The username if it was part of the URL, `None` otherwise. + Unlike :attr:`username` this one is not being decoded. + """ + return self._split_auth()[0] + + @property + def password(self) -> t.Optional[str]: + """The password if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a string. + """ + rv = self._split_auth()[1] + if rv is not None: + return _url_unquote_legacy(rv) + return None + + @property + def raw_password(self) -> t.Optional[str]: + """The password if it was part of the URL, `None` otherwise. + Unlike :attr:`password` this one is not being decoded. + """ + return self._split_auth()[1] + + def decode_query(self, *args: t.Any, **kwargs: t.Any) -> "ds.MultiDict[str, str]": + """Decodes the query part of the URL. Ths is a shortcut for + calling :func:`url_decode` on the query argument. The arguments and + keyword arguments are forwarded to :func:`url_decode` unchanged. + """ + return url_decode(self.query, *args, **kwargs) + + def join(self, *args: t.Any, **kwargs: t.Any) -> "BaseURL": + """Joins this URL with another one. This is just a convenience + function for calling into :meth:`url_join` and then parsing the + return value again. + """ + return url_parse(url_join(self, *args, **kwargs)) + + def to_url(self) -> str: + """Returns a URL string or bytes depending on the type of the + information stored. This is just a convenience function + for calling :meth:`url_unparse` for this URL. + """ + return url_unparse(self) + + def encode_netloc(self) -> str: + """Encodes the netloc part to an ASCII safe URL as bytes.""" + rv = self.ascii_host or "" + if ":" in rv: + rv = f"[{rv}]" + port = self.port + if port is not None: + rv = f"{rv}:{port}" + auth = ":".join( + filter( + None, + [ + url_quote(self.raw_username or "", "utf-8", "strict", "/:%"), + url_quote(self.raw_password or "", "utf-8", "strict", "/:%"), + ], + ) + ) + if auth: + rv = f"{auth}@{rv}" + return rv + + def decode_netloc(self) -> str: + """Decodes the netloc part into a string.""" + rv = _decode_idna(self.host or "") + + if ":" in rv: + rv = f"[{rv}]" + port = self.port + if port is not None: + rv = f"{rv}:{port}" + auth = ":".join( + filter( + None, + [ + _url_unquote_legacy(self.raw_username or "", "/:%@"), + _url_unquote_legacy(self.raw_password or "", "/:%@"), + ], + ) + ) + if auth: + rv = f"{auth}@{rv}" + return rv + + def to_uri_tuple(self) -> "BaseURL": + """Returns a :class:`BytesURL` tuple that holds a URI. This will + encode all the information in the URL properly to ASCII using the + rules a web browser would follow. + + It's usually more interesting to directly call :meth:`iri_to_uri` which + will return a string. + """ + return url_parse(iri_to_uri(self)) + + def to_iri_tuple(self) -> "BaseURL": + """Returns a :class:`URL` tuple that holds a IRI. This will try + to decode as much information as possible in the URL without + losing information similar to how a web browser does it for the + URL bar. + + It's usually more interesting to directly call :meth:`uri_to_iri` which + will return a string. + """ + return url_parse(uri_to_iri(self)) + + def get_file_location( + self, pathformat: t.Optional[str] = None + ) -> t.Tuple[t.Optional[str], t.Optional[str]]: + """Returns a tuple with the location of the file in the form + ``(server, location)``. If the netloc is empty in the URL or + points to localhost, it's represented as ``None``. + + The `pathformat` by default is autodetection but needs to be set + when working with URLs of a specific system. The supported values + are ``'windows'`` when working with Windows or DOS paths and + ``'posix'`` when working with posix paths. + + If the URL does not point to a local file, the server and location + are both represented as ``None``. + + :param pathformat: The expected format of the path component. + Currently ``'windows'`` and ``'posix'`` are + supported. Defaults to ``None`` which is + autodetect. + """ + if self.scheme != "file": + return None, None + + path = url_unquote(self.path) + host = self.netloc or None + + if pathformat is None: + if os.name == "nt": + pathformat = "windows" + else: + pathformat = "posix" + + if pathformat == "windows": + if path[:1] == "/" and path[1:2].isalpha() and path[2:3] in "|:": + path = f"{path[1:2]}:{path[3:]}" + windows_share = path[:3] in ("\\" * 3, "/" * 3) + import ntpath + + path = ntpath.normpath(path) + # Windows shared drives are represented as ``\\host\\directory``. + # That results in a URL like ``file://///host/directory``, and a + # path like ``///host/directory``. We need to special-case this + # because the path contains the hostname. + if windows_share and host is None: + parts = path.lstrip("\\").split("\\", 1) + if len(parts) == 2: + host, path = parts + else: + host = parts[0] + path = "" + elif pathformat == "posix": + import posixpath + + path = posixpath.normpath(path) + else: + raise TypeError(f"Invalid path format {pathformat!r}") + + if host in ("127.0.0.1", "::1", "localhost"): + host = None + + return host, path + + def _split_netloc(self) -> t.Tuple[t.Optional[str], str]: + if self._at in self.netloc: + auth, _, netloc = self.netloc.partition(self._at) + return auth, netloc + return None, self.netloc + + def _split_auth(self) -> t.Tuple[t.Optional[str], t.Optional[str]]: + auth = self._split_netloc()[0] + if not auth: + return None, None + if self._colon not in auth: + return auth, None + + username, _, password = auth.partition(self._colon) + return username, password + + def _split_host(self) -> t.Tuple[t.Optional[str], t.Optional[str]]: + rv = self._split_netloc()[1] + if not rv: + return None, None + + if not rv.startswith(self._lbracket): + if self._colon in rv: + host, _, port = rv.partition(self._colon) + return host, port + return rv, None + + idx = rv.find(self._rbracket) + if idx < 0: + return rv, None + + host = rv[1:idx] + rest = rv[idx + 1 :] + if rest.startswith(self._colon): + return host, rest[1:] + return host, None + + +class URL(BaseURL): + """Represents a parsed URL. This behaves like a regular tuple but + also has some extra attributes that give further insight into the + URL. + """ + + __slots__ = () + _at = "@" + _colon = ":" + _lbracket = "[" + _rbracket = "]" + + def encode(self, charset: str = "utf-8", errors: str = "replace") -> "BytesURL": + """Encodes the URL to a tuple made out of bytes. The charset is + only being used for the path, query and fragment. + """ + return BytesURL( + self.scheme.encode("ascii"), # type: ignore + self.encode_netloc(), + self.path.encode(charset, errors), # type: ignore + self.query.encode(charset, errors), # type: ignore + self.fragment.encode(charset, errors), # type: ignore + ) + + +class BytesURL(BaseURL): + """Represents a parsed URL in bytes.""" + + __slots__ = () + _at = b"@" # type: ignore + _colon = b":" # type: ignore + _lbracket = b"[" # type: ignore + _rbracket = b"]" # type: ignore + + def __str__(self) -> str: + return self.to_url().decode("utf-8", "replace") # type: ignore + + def encode_netloc(self) -> bytes: # type: ignore + """Returns the netloc unchanged as bytes.""" + return self.netloc # type: ignore + + def decode(self, charset: str = "utf-8", errors: str = "replace") -> "URL": + """Decodes the URL to a tuple made out of strings. The charset is + only being used for the path, query and fragment. + """ + return URL( + self.scheme.decode("ascii"), # type: ignore + self.decode_netloc(), + self.path.decode(charset, errors), # type: ignore + self.query.decode(charset, errors), # type: ignore + self.fragment.decode(charset, errors), # type: ignore + ) + + +_unquote_maps: t.Dict[t.FrozenSet[int], t.Dict[bytes, int]] = {frozenset(): _hextobyte} + + +def _unquote_to_bytes( + string: t.Union[str, bytes], unsafe: t.Union[str, bytes] = "" +) -> bytes: + if isinstance(string, str): + string = string.encode("utf-8") + + if isinstance(unsafe, str): + unsafe = unsafe.encode("utf-8") + + unsafe = frozenset(bytearray(unsafe)) + groups = iter(string.split(b"%")) + result = bytearray(next(groups, b"")) + + try: + hex_to_byte = _unquote_maps[unsafe] + except KeyError: + hex_to_byte = _unquote_maps[unsafe] = { + h: b for h, b in _hextobyte.items() if b not in unsafe + } + + for group in groups: + code = group[:2] + + if code in hex_to_byte: + result.append(hex_to_byte[code]) + result.extend(group[2:]) + else: + result.append(37) # % + result.extend(group) + + return bytes(result) + + +def _url_encode_impl( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + charset: str, + sort: bool, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]], +) -> t.Iterator[str]: + from .datastructures import iter_multi_items + + iterable: t.Iterable[t.Tuple[str, str]] = iter_multi_items(obj) + + if sort: + iterable = sorted(iterable, key=key) + + for key_str, value_str in iterable: + if value_str is None: + continue + + if not isinstance(key_str, bytes): + key_bytes = str(key_str).encode(charset) + else: + key_bytes = key_str + + if not isinstance(value_str, bytes): + value_bytes = str(value_str).encode(charset) + else: + value_bytes = value_str + + yield f"{_fast_url_quote_plus(key_bytes)}={_fast_url_quote_plus(value_bytes)}" + + +def _url_unquote_legacy(value: str, unsafe: str = "") -> str: + try: + return url_unquote(value, charset="utf-8", errors="strict", unsafe=unsafe) + except UnicodeError: + return url_unquote(value, charset="latin1", unsafe=unsafe) + + +def url_parse( + url: str, scheme: t.Optional[str] = None, allow_fragments: bool = True +) -> BaseURL: + """Parses a URL from a string into a :class:`URL` tuple. If the URL + is lacking a scheme it can be provided as second argument. Otherwise, + it is ignored. Optionally fragments can be stripped from the URL + by setting `allow_fragments` to `False`. + + The inverse of this function is :func:`url_unparse`. + + :param url: the URL to parse. + :param scheme: the default schema to use if the URL is schemaless. + :param allow_fragments: if set to `False` a fragment will be removed + from the URL. + """ + s = _make_encode_wrapper(url) + is_text_based = isinstance(url, str) + + if scheme is None: + scheme = s("") + netloc = query = fragment = s("") + i = url.find(s(":")) + if i > 0 and _scheme_re.match(_to_str(url[:i], errors="replace")): + # make sure "iri" is not actually a port number (in which case + # "scheme" is really part of the path) + rest = url[i + 1 :] + if not rest or any(c not in s("0123456789") for c in rest): + # not a port number + scheme, url = url[:i].lower(), rest + + if url[:2] == s("//"): + delim = len(url) + for c in s("/?#"): + wdelim = url.find(c, 2) + if wdelim >= 0: + delim = min(delim, wdelim) + netloc, url = url[2:delim], url[delim:] + if (s("[") in netloc and s("]") not in netloc) or ( + s("]") in netloc and s("[") not in netloc + ): + raise ValueError("Invalid IPv6 URL") + + if allow_fragments and s("#") in url: + url, fragment = url.split(s("#"), 1) + if s("?") in url: + url, query = url.split(s("?"), 1) + + result_type = URL if is_text_based else BytesURL + return result_type(scheme, netloc, url, query, fragment) + + +def _make_fast_url_quote( + charset: str = "utf-8", + errors: str = "strict", + safe: t.Union[str, bytes] = "/:", + unsafe: t.Union[str, bytes] = "", +) -> t.Callable[[bytes], str]: + """Precompile the translation table for a URL encoding function. + + Unlike :func:`url_quote`, the generated function only takes the + string to quote. + + :param charset: The charset to encode the result with. + :param errors: How to handle encoding errors. + :param safe: An optional sequence of safe characters to never encode. + :param unsafe: An optional sequence of unsafe characters to always encode. + """ + if isinstance(safe, str): + safe = safe.encode(charset, errors) + + if isinstance(unsafe, str): + unsafe = unsafe.encode(charset, errors) + + safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) + table = [chr(c) if c in safe else f"%{c:02X}" for c in range(256)] + + def quote(string: bytes) -> str: + return "".join([table[c] for c in string]) + + return quote + + +_fast_url_quote = _make_fast_url_quote() +_fast_quote_plus = _make_fast_url_quote(safe=" ", unsafe="+") + + +def _fast_url_quote_plus(string: bytes) -> str: + return _fast_quote_plus(string).replace(" ", "+") + + +def url_quote( + string: t.Union[str, bytes], + charset: str = "utf-8", + errors: str = "strict", + safe: t.Union[str, bytes] = "/:", + unsafe: t.Union[str, bytes] = "", +) -> str: + """URL encode a single string with a given encoding. + + :param s: the string to quote. + :param charset: the charset to be used. + :param safe: an optional sequence of safe characters. + :param unsafe: an optional sequence of unsafe characters. + + .. versionadded:: 0.9.2 + The `unsafe` parameter was added. + """ + if not isinstance(string, (str, bytes, bytearray)): + string = str(string) + if isinstance(string, str): + string = string.encode(charset, errors) + if isinstance(safe, str): + safe = safe.encode(charset, errors) + if isinstance(unsafe, str): + unsafe = unsafe.encode(charset, errors) + safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) + rv = bytearray() + for char in bytearray(string): + if char in safe: + rv.append(char) + else: + rv.extend(_bytetohex[char]) + return bytes(rv).decode(charset) + + +def url_quote_plus( + string: str, charset: str = "utf-8", errors: str = "strict", safe: str = "" +) -> str: + """URL encode a single string with the given encoding and convert + whitespace to "+". + + :param s: The string to quote. + :param charset: The charset to be used. + :param safe: An optional sequence of safe characters. + """ + return url_quote(string, charset, errors, safe + " ", "+").replace(" ", "+") + + +def url_unparse(components: t.Tuple[str, str, str, str, str]) -> str: + """The reverse operation to :meth:`url_parse`. This accepts arbitrary + as well as :class:`URL` tuples and returns a URL as a string. + + :param components: the parsed URL as tuple which should be converted + into a URL string. + """ + _check_str_tuple(components) + scheme, netloc, path, query, fragment = components + s = _make_encode_wrapper(scheme) + url = s("") + + # We generally treat file:///x and file:/x the same which is also + # what browsers seem to do. This also allows us to ignore a schema + # register for netloc utilization or having to differentiate between + # empty and missing netloc. + if netloc or (scheme and path.startswith(s("/"))): + if path and path[:1] != s("/"): + path = s("/") + path + url = s("//") + (netloc or s("")) + path + elif path: + url += path + if scheme: + url = scheme + s(":") + url + if query: + url = url + s("?") + query + if fragment: + url = url + s("#") + fragment + return url + + +def url_unquote( + s: t.Union[str, bytes], + charset: str = "utf-8", + errors: str = "replace", + unsafe: str = "", +) -> str: + """URL decode a single string with a given encoding. If the charset + is set to `None` no decoding is performed and raw bytes are + returned. + + :param s: the string to unquote. + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param errors: the error handling for the charset decoding. + """ + rv = _unquote_to_bytes(s, unsafe) + if charset is None: + return rv + return rv.decode(charset, errors) + + +def url_unquote_plus( + s: t.Union[str, bytes], charset: str = "utf-8", errors: str = "replace" +) -> str: + """URL decode a single string with the given `charset` and decode "+" to + whitespace. + + Per default encoding errors are ignored. If you want a different behavior + you can set `errors` to ``'replace'`` or ``'strict'``. + + :param s: The string to unquote. + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param errors: The error handling for the `charset` decoding. + """ + if isinstance(s, str): + s = s.replace("+", " ") + else: + s = s.replace(b"+", b" ") + return url_unquote(s, charset, errors) + + +def url_fix(s: str, charset: str = "utf-8") -> str: + r"""Sometimes you get an URL by a user that just isn't a real URL because + it contains unsafe characters like ' ' and so on. This function can fix + some of the problems in a similar way browsers handle data entered by the + user: + + >>> url_fix('http://de.wikipedia.org/wiki/Elf (Begriffskl\xe4rung)') + 'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)' + + :param s: the string with the URL to fix. + :param charset: The target charset for the URL if the url was given + as a string. + """ + # First step is to switch to text processing and to convert + # backslashes (which are invalid in URLs anyways) to slashes. This is + # consistent with what Chrome does. + s = _to_str(s, charset, "replace").replace("\\", "/") + + # For the specific case that we look like a malformed windows URL + # we want to fix this up manually: + if s.startswith("file://") and s[7:8].isalpha() and s[8:10] in (":/", "|/"): + s = f"file:///{s[7:]}" + + url = url_parse(s) + path = url_quote(url.path, charset, safe="/%+$!*'(),") + qs = url_quote_plus(url.query, charset, safe=":&%=+$!*'(),") + anchor = url_quote_plus(url.fragment, charset, safe=":&%=+$!*'(),") + return url_unparse((url.scheme, url.encode_netloc(), path, qs, anchor)) + + +# not-unreserved characters remain quoted when unquoting to IRI +_to_iri_unsafe = "".join([chr(c) for c in range(128) if c not in _always_safe]) + + +def _codec_error_url_quote(e: UnicodeError) -> t.Tuple[str, int]: + """Used in :func:`uri_to_iri` after unquoting to re-quote any + invalid bytes. + """ + # the docs state that UnicodeError does have these attributes, + # but mypy isn't picking them up + out = _fast_url_quote(e.object[e.start : e.end]) # type: ignore + return out, e.end # type: ignore + + +codecs.register_error("werkzeug.url_quote", _codec_error_url_quote) + + +def uri_to_iri( + uri: t.Union[str, t.Tuple[str, str, str, str, str]], + charset: str = "utf-8", + errors: str = "werkzeug.url_quote", +) -> str: + """Convert a URI to an IRI. All valid UTF-8 characters are unquoted, + leaving all reserved and invalid characters quoted. If the URL has + a domain, it is decoded from Punycode. + + >>> uri_to_iri("http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF") + 'http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF' + + :param uri: The URI to convert. + :param charset: The encoding to encode unquoted bytes with. + :param errors: Error handler to use during ``bytes.encode``. By + default, invalid bytes are left quoted. + + .. versionchanged:: 0.15 + All reserved and invalid characters remain quoted. Previously, + only some reserved characters were preserved, and invalid bytes + were replaced instead of left quoted. + + .. versionadded:: 0.6 + """ + if isinstance(uri, tuple): + uri = url_unparse(uri) + + uri = url_parse(_to_str(uri, charset)) + path = url_unquote(uri.path, charset, errors, _to_iri_unsafe) + query = url_unquote(uri.query, charset, errors, _to_iri_unsafe) + fragment = url_unquote(uri.fragment, charset, errors, _to_iri_unsafe) + return url_unparse((uri.scheme, uri.decode_netloc(), path, query, fragment)) + + +# reserved characters remain unquoted when quoting to URI +_to_uri_safe = ":/?#[]@!$&'()*+,;=%" + + +def iri_to_uri( + iri: t.Union[str, t.Tuple[str, str, str, str, str]], + charset: str = "utf-8", + errors: str = "strict", + safe_conversion: bool = False, +) -> str: + """Convert an IRI to a URI. All non-ASCII and unsafe characters are + quoted. If the URL has a domain, it is encoded to Punycode. + + >>> iri_to_uri('http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF') + 'http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF' + + :param iri: The IRI to convert. + :param charset: The encoding of the IRI. + :param errors: Error handler to use during ``bytes.encode``. + :param safe_conversion: Return the URL unchanged if it only contains + ASCII characters and no whitespace. See the explanation below. + + There is a general problem with IRI conversion with some protocols + that are in violation of the URI specification. Consider the + following two IRIs:: + + magnet:?xt=uri:whatever + itms-services://?action=download-manifest + + After parsing, we don't know if the scheme requires the ``//``, + which is dropped if empty, but conveys different meanings in the + final URL if it's present or not. In this case, you can use + ``safe_conversion``, which will return the URL unchanged if it only + contains ASCII characters and no whitespace. This can result in a + URI with unquoted characters if it was not already quoted correctly, + but preserves the URL's semantics. Werkzeug uses this for the + ``Location`` header for redirects. + + .. versionchanged:: 0.15 + All reserved characters remain unquoted. Previously, only some + reserved characters were left unquoted. + + .. versionchanged:: 0.9.6 + The ``safe_conversion`` parameter was added. + + .. versionadded:: 0.6 + """ + if isinstance(iri, tuple): + iri = url_unparse(iri) + + if safe_conversion: + # If we're not sure if it's safe to convert the URL, and it only + # contains ASCII characters, return it unconverted. + try: + native_iri = _to_str(iri) + ascii_iri = native_iri.encode("ascii") + + # Only return if it doesn't have whitespace. (Why?) + if len(ascii_iri.split()) == 1: + return native_iri + except UnicodeError: + pass + + iri = url_parse(_to_str(iri, charset, errors)) + path = url_quote(iri.path, charset, errors, _to_uri_safe) + query = url_quote(iri.query, charset, errors, _to_uri_safe) + fragment = url_quote(iri.fragment, charset, errors, _to_uri_safe) + return url_unparse((iri.scheme, iri.encode_netloc(), path, query, fragment)) + + +def url_decode( + s: t.AnyStr, + charset: str = "utf-8", + include_empty: bool = True, + errors: str = "replace", + separator: str = "&", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, +) -> "ds.MultiDict[str, str]": + """Parse a query string and return it as a :class:`MultiDict`. + + :param s: The query string to parse. + :param charset: Decode bytes to string with this charset. If not + given, bytes are returned as-is. + :param include_empty: Include keys with empty values in the dict. + :param errors: Error handling behavior when decoding bytes. + :param separator: Separator character between pairs. + :param cls: Container to hold result instead of :class:`MultiDict`. + + .. versionchanged:: 2.0 + The ``decode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + In previous versions ";" and "&" could be used for url decoding. + Now only "&" is supported. If you want to use ";", a different + ``separator`` can be provided. + + .. versionchanged:: 0.5 + The ``cls`` parameter was added. + """ + if cls is None: + from .datastructures import MultiDict # noqa: F811 + + cls = MultiDict + if isinstance(s, str) and not isinstance(separator, str): + separator = separator.decode(charset or "ascii") + elif isinstance(s, bytes) and not isinstance(separator, bytes): + separator = separator.encode(charset or "ascii") # type: ignore + return cls( + _url_decode_impl( + s.split(separator), charset, include_empty, errors # type: ignore + ) + ) + + +def url_decode_stream( + stream: t.IO[bytes], + charset: str = "utf-8", + include_empty: bool = True, + errors: str = "replace", + separator: bytes = b"&", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, + limit: t.Optional[int] = None, +) -> "ds.MultiDict[str, str]": + """Works like :func:`url_decode` but decodes a stream. The behavior + of stream and limit follows functions like + :func:`~werkzeug.wsgi.make_line_iter`. The generator of pairs is + directly fed to the `cls` so you can consume the data while it's + parsed. + + :param stream: a stream with the encoded querystring + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param include_empty: Set to `False` if you don't want empty values to + appear in the dict. + :param errors: the decoding error behavior. + :param separator: the pair separator to be used, defaults to ``&`` + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param limit: the content length of the URL data. Not necessary if + a limited stream is provided. + + .. versionchanged:: 2.0 + The ``decode_keys`` and ``return_iterator`` parameters are + deprecated and will be removed in Werkzeug 2.1. + + .. versionadded:: 0.8 + """ + from .wsgi import make_chunk_iter + + pair_iter = make_chunk_iter(stream, separator, limit) + decoder = _url_decode_impl(pair_iter, charset, include_empty, errors) + + if cls is None: + from .datastructures import MultiDict # noqa: F811 + + cls = MultiDict + + return cls(decoder) + + +def _url_decode_impl( + pair_iter: t.Iterable[t.AnyStr], charset: str, include_empty: bool, errors: str +) -> t.Iterator[t.Tuple[str, str]]: + for pair in pair_iter: + if not pair: + continue + s = _make_encode_wrapper(pair) + equal = s("=") + if equal in pair: + key, value = pair.split(equal, 1) + else: + if not include_empty: + continue + key = pair + value = s("") + yield ( + url_unquote_plus(key, charset, errors), + url_unquote_plus(value, charset, errors), + ) + + +def url_encode( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + charset: str = "utf-8", + sort: bool = False, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]] = None, + separator: str = "&", +) -> str: + """URL encode a dict/`MultiDict`. If a value is `None` it will not appear + in the result string. Per default only values are encoded into the target + charset strings. + + :param obj: the object to encode into a query string. + :param charset: the charset of the query string. + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + + .. versionchanged:: 2.0 + The ``encode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + Added the ``sort``, ``key``, and ``separator`` parameters. + """ + separator = _to_str(separator, "ascii") + return separator.join(_url_encode_impl(obj, charset, sort, key)) + + +def url_encode_stream( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + stream: t.Optional[t.IO[str]] = None, + charset: str = "utf-8", + sort: bool = False, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]] = None, + separator: str = "&", +) -> None: + """Like :meth:`url_encode` but writes the results to a stream + object. If the stream is `None` a generator over all encoded + pairs is returned. + + :param obj: the object to encode into a query string. + :param stream: a stream to write the encoded object into or `None` if + an iterator over the encoded pairs should be returned. In + that case the separator argument is ignored. + :param charset: the charset of the query string. + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + + .. versionchanged:: 2.0 + The ``encode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionadded:: 0.8 + """ + separator = _to_str(separator, "ascii") + gen = _url_encode_impl(obj, charset, sort, key) + if stream is None: + return gen # type: ignore + for idx, chunk in enumerate(gen): + if idx: + stream.write(separator) + stream.write(chunk) + return None + + +def url_join( + base: t.Union[str, t.Tuple[str, str, str, str, str]], + url: t.Union[str, t.Tuple[str, str, str, str, str]], + allow_fragments: bool = True, +) -> str: + """Join a base URL and a possibly relative URL to form an absolute + interpretation of the latter. + + :param base: the base URL for the join operation. + :param url: the URL to join. + :param allow_fragments: indicates whether fragments should be allowed. + """ + if isinstance(base, tuple): + base = url_unparse(base) + if isinstance(url, tuple): + url = url_unparse(url) + + _check_str_tuple((base, url)) + s = _make_encode_wrapper(base) + + if not base: + return url + if not url: + return base + + bscheme, bnetloc, bpath, bquery, bfragment = url_parse( + base, allow_fragments=allow_fragments + ) + scheme, netloc, path, query, fragment = url_parse(url, bscheme, allow_fragments) + if scheme != bscheme: + return url + if netloc: + return url_unparse((scheme, netloc, path, query, fragment)) + netloc = bnetloc + + if path[:1] == s("/"): + segments = path.split(s("/")) + elif not path: + segments = bpath.split(s("/")) + if not query: + query = bquery + else: + segments = bpath.split(s("/"))[:-1] + path.split(s("/")) + + # If the rightmost part is "./" we want to keep the slash but + # remove the dot. + if segments[-1] == s("."): + segments[-1] = s("") + + # Resolve ".." and "." + segments = [segment for segment in segments if segment != s(".")] + while True: + i = 1 + n = len(segments) - 1 + while i < n: + if segments[i] == s("..") and segments[i - 1] not in (s(""), s("..")): + del segments[i - 1 : i + 1] + break + i += 1 + else: + break + + # Remove trailing ".." if the URL is absolute + unwanted_marker = [s(""), s("..")] + while segments[:2] == unwanted_marker: + del segments[1] + + path = s("/").join(segments) + return url_unparse((scheme, netloc, path, query, fragment)) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/user_agent.py b/axios-example/lib/python3.10/site-packages/werkzeug/user_agent.py new file mode 100644 index 0000000..66ffcbe --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/user_agent.py @@ -0,0 +1,47 @@ +import typing as t + + +class UserAgent: + """Represents a parsed user agent header value. + + The default implementation does no parsing, only the :attr:`string` + attribute is set. A subclass may parse the string to set the + common attributes or expose other information. Set + :attr:`werkzeug.wrappers.Request.user_agent_class` to use a + subclass. + + :param string: The header value to parse. + + .. versionadded:: 2.0 + This replaces the previous ``useragents`` module, but does not + provide a built-in parser. + """ + + platform: t.Optional[str] = None + """The OS name, if it could be parsed from the string.""" + + browser: t.Optional[str] = None + """The browser name, if it could be parsed from the string.""" + + version: t.Optional[str] = None + """The browser version, if it could be parsed from the string.""" + + language: t.Optional[str] = None + """The browser language, if it could be parsed from the string.""" + + def __init__(self, string: str) -> None: + self.string: str = string + """The original header value.""" + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.browser}/{self.version}>" + + def __str__(self) -> str: + return self.string + + def __bool__(self) -> bool: + return bool(self.browser) + + def to_header(self) -> str: + """Convert to a header value.""" + return self.string diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/utils.py b/axios-example/lib/python3.10/site-packages/werkzeug/utils.py new file mode 100644 index 0000000..f94444e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/utils.py @@ -0,0 +1,705 @@ +import io +import mimetypes +import os +import pkgutil +import re +import sys +import typing as t +import unicodedata +from datetime import datetime +from time import time +from zlib import adler32 + +from ._internal import _DictAccessorProperty +from ._internal import _missing +from ._internal import _TAccessorValue +from .datastructures import Headers +from .exceptions import NotFound +from .exceptions import RequestedRangeNotSatisfiable +from .security import safe_join +from .urls import url_quote +from .wsgi import wrap_file + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + from .wrappers.request import Request + from .wrappers.response import Response + +_T = t.TypeVar("_T") + +_entity_re = re.compile(r"&([^;]+);") +_filename_ascii_strip_re = re.compile(r"[^A-Za-z0-9_.-]") +_windows_device_files = ( + "CON", + "AUX", + "COM1", + "COM2", + "COM3", + "COM4", + "LPT1", + "LPT2", + "LPT3", + "PRN", + "NUL", +) + + +class cached_property(property, t.Generic[_T]): + """A :func:`property` that is only evaluated once. Subsequent access + returns the cached value. Setting the property sets the cached + value. Deleting the property clears the cached value, accessing it + again will evaluate it again. + + .. code-block:: python + + class Example: + @cached_property + def value(self): + # calculate something important here + return 42 + + e = Example() + e.value # evaluates + e.value # uses cache + e.value = 16 # sets cache + del e.value # clears cache + + If the class defines ``__slots__``, it must add ``_cache_{name}`` as + a slot. Alternatively, it can add ``__dict__``, but that's usually + not desirable. + + .. versionchanged:: 2.1 + Works with ``__slots__``. + + .. versionchanged:: 2.0 + ``del obj.name`` clears the cached value. + """ + + def __init__( + self, + fget: t.Callable[[t.Any], _T], + name: t.Optional[str] = None, + doc: t.Optional[str] = None, + ) -> None: + super().__init__(fget, doc=doc) + self.__name__ = name or fget.__name__ + self.slot_name = f"_cache_{self.__name__}" + self.__module__ = fget.__module__ + + def __set__(self, obj: object, value: _T) -> None: + if hasattr(obj, "__dict__"): + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + def __get__(self, obj: object, type: type = None) -> _T: # type: ignore + if obj is None: + return self # type: ignore + + obj_dict = getattr(obj, "__dict__", None) + + if obj_dict is not None: + value: _T = obj_dict.get(self.__name__, _missing) + else: + value = getattr(obj, self.slot_name, _missing) # type: ignore[arg-type] + + if value is _missing: + value = self.fget(obj) # type: ignore + + if obj_dict is not None: + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + return value + + def __delete__(self, obj: object) -> None: + if hasattr(obj, "__dict__"): + del obj.__dict__[self.__name__] + else: + setattr(obj, self.slot_name, _missing) + + +class environ_property(_DictAccessorProperty[_TAccessorValue]): + """Maps request attributes to environment variables. This works not only + for the Werkzeug request object, but also any other class with an + environ attribute: + + >>> class Test(object): + ... environ = {'key': 'value'} + ... test = environ_property('key') + >>> var = Test() + >>> var.test + 'value' + + If you pass it a second value it's used as default if the key does not + exist, the third one can be a converter that takes a value and converts + it. If it raises :exc:`ValueError` or :exc:`TypeError` the default value + is used. If no default value is provided `None` is used. + + Per default the property is read only. You have to explicitly enable it + by passing ``read_only=False`` to the constructor. + """ + + read_only = True + + def lookup(self, obj: "Request") -> "WSGIEnvironment": + return obj.environ + + +class header_property(_DictAccessorProperty[_TAccessorValue]): + """Like `environ_property` but for headers.""" + + def lookup(self, obj: t.Union["Request", "Response"]) -> Headers: + return obj.headers + + +# https://cgit.freedesktop.org/xdg/shared-mime-info/tree/freedesktop.org.xml.in +# https://www.iana.org/assignments/media-types/media-types.xhtml +# Types listed in the XDG mime info that have a charset in the IANA registration. +_charset_mimetypes = { + "application/ecmascript", + "application/javascript", + "application/sql", + "application/xml", + "application/xml-dtd", + "application/xml-external-parsed-entity", +} + + +def get_content_type(mimetype: str, charset: str) -> str: + """Returns the full content type string with charset for a mimetype. + + If the mimetype represents text, the charset parameter will be + appended, otherwise the mimetype is returned unchanged. + + :param mimetype: The mimetype to be used as content type. + :param charset: The charset to be appended for text mimetypes. + :return: The content type. + + .. versionchanged:: 0.15 + Any type that ends with ``+xml`` gets a charset, not just those + that start with ``application/``. Known text types such as + ``application/javascript`` are also given charsets. + """ + if ( + mimetype.startswith("text/") + or mimetype in _charset_mimetypes + or mimetype.endswith("+xml") + ): + mimetype += f"; charset={charset}" + + return mimetype + + +def secure_filename(filename: str) -> str: + r"""Pass it a filename and it will return a secure version of it. This + filename can then safely be stored on a regular file system and passed + to :func:`os.path.join`. The filename returned is an ASCII only string + for maximum portability. + + On windows systems the function also makes sure that the file is not + named after one of the special device files. + + >>> secure_filename("My cool movie.mov") + 'My_cool_movie.mov' + >>> secure_filename("../../../etc/passwd") + 'etc_passwd' + >>> secure_filename('i contain cool \xfcml\xe4uts.txt') + 'i_contain_cool_umlauts.txt' + + The function might return an empty filename. It's your responsibility + to ensure that the filename is unique and that you abort or + generate a random filename if the function returned an empty one. + + .. versionadded:: 0.5 + + :param filename: the filename to secure + """ + filename = unicodedata.normalize("NFKD", filename) + filename = filename.encode("ascii", "ignore").decode("ascii") + + for sep in os.path.sep, os.path.altsep: + if sep: + filename = filename.replace(sep, " ") + filename = str(_filename_ascii_strip_re.sub("", "_".join(filename.split()))).strip( + "._" + ) + + # on nt a couple of special files are present in each folder. We + # have to ensure that the target file is not such a filename. In + # this case we prepend an underline + if ( + os.name == "nt" + and filename + and filename.split(".")[0].upper() in _windows_device_files + ): + filename = f"_{filename}" + + return filename + + +def redirect( + location: str, code: int = 302, Response: t.Optional[t.Type["Response"]] = None +) -> "Response": + """Returns a response object (a WSGI application) that, if called, + redirects the client to the target location. Supported codes are + 301, 302, 303, 305, 307, and 308. 300 is not supported because + it's not a real redirect and 304 because it's the answer for a + request with a request with defined If-Modified-Since headers. + + .. versionadded:: 0.6 + The location can now be a unicode string that is encoded using + the :func:`iri_to_uri` function. + + .. versionadded:: 0.10 + The class used for the Response object can now be passed in. + + :param location: the location the response should redirect to. + :param code: the redirect status code. defaults to 302. + :param class Response: a Response class to use when instantiating a + response. The default is :class:`werkzeug.wrappers.Response` if + unspecified. + """ + import html + + if Response is None: + from .wrappers import Response # type: ignore + + display_location = html.escape(location) + if isinstance(location, str): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + from .urls import iri_to_uri + + location = iri_to_uri(location, safe_conversion=True) + + response = Response( # type: ignore + "\n" + "\n" + "Redirecting...\n" + "

    Redirecting...

    \n" + "

    You should be redirected automatically to the target URL: " + f'{display_location}. If' + " not, click the link.\n", + code, + mimetype="text/html", + ) + response.headers["Location"] = location + return response + + +def append_slash_redirect(environ: "WSGIEnvironment", code: int = 308) -> "Response": + """Redirect to the current URL with a slash appended. + + If the current URL is ``/user/42``, the redirect URL will be + ``42/``. When joined to the current URL during response + processing or by the browser, this will produce ``/user/42/``. + + The behavior is undefined if the path ends with a slash already. If + called unconditionally on a URL, it may produce a redirect loop. + + :param environ: Use the path and query from this WSGI environment + to produce the redirect URL. + :param code: the status code for the redirect. + + .. versionchanged:: 2.1 + Produce a relative URL that only modifies the last segment. + Relevant when the current path has multiple segments. + + .. versionchanged:: 2.1 + The default status code is 308 instead of 301. This preserves + the request method and body. + """ + tail = environ["PATH_INFO"].rpartition("/")[2] + + if not tail: + new_path = "./" + else: + new_path = f"{tail}/" + + query_string = environ.get("QUERY_STRING") + + if query_string: + new_path = f"{new_path}?{query_string}" + + return redirect(new_path, code) + + +def send_file( + path_or_file: t.Union[os.PathLike, str, t.IO[bytes]], + environ: "WSGIEnvironment", + mimetype: t.Optional[str] = None, + as_attachment: bool = False, + download_name: t.Optional[str] = None, + conditional: bool = True, + etag: t.Union[bool, str] = True, + last_modified: t.Optional[t.Union[datetime, int, float]] = None, + max_age: t.Optional[ + t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]] + ] = None, + use_x_sendfile: bool = False, + response_class: t.Optional[t.Type["Response"]] = None, + _root_path: t.Optional[t.Union[os.PathLike, str]] = None, +) -> "Response": + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, ``use_x_sendfile=True`` + will tell the server to send the given path, which is much more + efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param environ: The WSGI environ for the current request. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + :param use_x_sendfile: Set the ``X-Sendfile`` header to let the + server to efficiently send the file. Requires support from the + HTTP server. Requires passing a file path. + :param response_class: Build the response using this class. Defaults + to :class:`~werkzeug.wrappers.Response`. + :param _root_path: Do not use. For internal use only. Use + :func:`send_from_directory` to safely send files under a path. + + .. versionchanged:: 2.0.2 + ``send_file`` only sets a detected ``Content-Encoding`` if + ``as_attachment`` is disabled. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + + .. versionchanged:: 2.0 + ``download_name`` replaces Flask's ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces Flask's ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces Flask's ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + If an encoding is returned when guessing ``mimetype`` from + ``download_name``, set the ``Content-Encoding`` header. + """ + if response_class is None: + from .wrappers import Response + + response_class = Response + + path: t.Optional[str] = None + file: t.Optional[t.IO[bytes]] = None + size: t.Optional[int] = None + mtime: t.Optional[float] = None + headers = Headers() + + if isinstance(path_or_file, (os.PathLike, str)) or hasattr( + path_or_file, "__fspath__" + ): + path_or_file = t.cast(t.Union[os.PathLike, str], path_or_file) + + # Flask will pass app.root_path, allowing its send_file wrapper + # to not have to deal with paths. + if _root_path is not None: + path = os.path.join(_root_path, path_or_file) + else: + path = os.path.abspath(path_or_file) + + stat = os.stat(path) + size = stat.st_size + mtime = stat.st_mtime + else: + file = path_or_file + + if download_name is None and path is not None: + download_name = os.path.basename(path) + + if mimetype is None: + if download_name is None: + raise TypeError( + "Unable to detect the MIME type because a file name is" + " not available. Either set 'download_name', pass a" + " path instead of a file, or set 'mimetype'." + ) + + mimetype, encoding = mimetypes.guess_type(download_name) + + if mimetype is None: + mimetype = "application/octet-stream" + + # Don't send encoding for attachments, it causes browsers to + # save decompress tar.gz files. + if encoding is not None and not as_attachment: + headers.set("Content-Encoding", encoding) + + if download_name is not None: + try: + download_name.encode("ascii") + except UnicodeEncodeError: + simple = unicodedata.normalize("NFKD", download_name) + simple = simple.encode("ascii", "ignore").decode("ascii") + quoted = url_quote(download_name, safe="") + names = {"filename": simple, "filename*": f"UTF-8''{quoted}"} + else: + names = {"filename": download_name} + + value = "attachment" if as_attachment else "inline" + headers.set("Content-Disposition", value, **names) + elif as_attachment: + raise TypeError( + "No name provided for attachment. Either set" + " 'download_name' or pass a path instead of a file." + ) + + if use_x_sendfile and path is not None: + headers["X-Sendfile"] = path + data = None + else: + if file is None: + file = open(path, "rb") # type: ignore + elif isinstance(file, io.BytesIO): + size = file.getbuffer().nbytes + elif isinstance(file, io.TextIOBase): + raise ValueError("Files must be opened in binary mode or use BytesIO.") + + data = wrap_file(environ, file) + + rv = response_class( + data, mimetype=mimetype, headers=headers, direct_passthrough=True + ) + + if size is not None: + rv.content_length = size + + if last_modified is not None: + rv.last_modified = last_modified # type: ignore + elif mtime is not None: + rv.last_modified = mtime # type: ignore + + rv.cache_control.no_cache = True + + # Flask will pass app.get_send_file_max_age, allowing its send_file + # wrapper to not have to deal with paths. + if callable(max_age): + max_age = max_age(path) + + if max_age is not None: + if max_age > 0: + rv.cache_control.no_cache = None + rv.cache_control.public = True + + rv.cache_control.max_age = max_age + rv.expires = int(time() + max_age) # type: ignore + + if isinstance(etag, str): + rv.set_etag(etag) + elif etag and path is not None: + check = adler32(path.encode("utf-8")) & 0xFFFFFFFF + rv.set_etag(f"{mtime}-{size}-{check}") + + if conditional: + try: + rv = rv.make_conditional(environ, accept_ranges=True, complete_length=size) + except RequestedRangeNotSatisfiable: + if file is not None: + file.close() + + raise + + # Some x-sendfile implementations incorrectly ignore the 304 + # status code and send the file anyway. + if rv.status_code == 304: + rv.headers.pop("x-sendfile", None) + + return rv + + +def send_from_directory( + directory: t.Union[os.PathLike, str], + path: t.Union[os.PathLike, str], + environ: "WSGIEnvironment", + **kwargs: t.Any, +) -> "Response": + """Send a file from within a directory using :func:`send_file`. + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + returns a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under. + :param path: The path to the file to send, relative to + ``directory``. + :param environ: The WSGI environ for the current request. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + """ + path = safe_join(os.fspath(directory), os.fspath(path)) + + if path is None: + raise NotFound() + + # Flask will pass app.root_path, allowing its send_from_directory + # wrapper to not have to deal with paths. + if "_root_path" in kwargs: + path = os.path.join(kwargs["_root_path"], path) + + try: + if not os.path.isfile(path): + raise NotFound() + except ValueError: + # path contains null byte on Python < 3.8 + raise NotFound() from None + + return send_file(path, environ, **kwargs) + + +def import_string(import_name: str, silent: bool = False) -> t.Any: + """Imports an object based on a string. This is useful if you want to + use import paths as endpoints or something similar. An import path can + be specified either in dotted notation (``xml.sax.saxutils.escape``) + or with a colon as object delimiter (``xml.sax.saxutils:escape``). + + If `silent` is True the return value will be `None` if the import fails. + + :param import_name: the dotted name for the object to import. + :param silent: if set to `True` import errors are ignored and + `None` is returned instead. + :return: imported object + """ + import_name = import_name.replace(":", ".") + try: + try: + __import__(import_name) + except ImportError: + if "." not in import_name: + raise + else: + return sys.modules[import_name] + + module_name, obj_name = import_name.rsplit(".", 1) + module = __import__(module_name, globals(), locals(), [obj_name]) + try: + return getattr(module, obj_name) + except AttributeError as e: + raise ImportError(e) from None + + except ImportError as e: + if not silent: + raise ImportStringError(import_name, e).with_traceback( + sys.exc_info()[2] + ) from None + + return None + + +def find_modules( + import_path: str, include_packages: bool = False, recursive: bool = False +) -> t.Iterator[str]: + """Finds all the modules below a package. This can be useful to + automatically import all views / controllers so that their metaclasses / + function decorators have a chance to register themselves on the + application. + + Packages are not returned unless `include_packages` is `True`. This can + also recursively list modules but in that case it will import all the + packages to get the correct load path of that module. + + :param import_path: the dotted name for the package to find child modules. + :param include_packages: set to `True` if packages should be returned, too. + :param recursive: set to `True` if recursion should happen. + :return: generator + """ + module = import_string(import_path) + path = getattr(module, "__path__", None) + if path is None: + raise ValueError(f"{import_path!r} is not a package") + basename = f"{module.__name__}." + for _importer, modname, ispkg in pkgutil.iter_modules(path): + modname = basename + modname + if ispkg: + if include_packages: + yield modname + if recursive: + yield from find_modules(modname, include_packages, True) + else: + yield modname + + +class ImportStringError(ImportError): + """Provides information about a failed :func:`import_string` attempt.""" + + #: String in dotted notation that failed to be imported. + import_name: str + #: Wrapped exception. + exception: BaseException + + def __init__(self, import_name: str, exception: BaseException) -> None: + self.import_name = import_name + self.exception = exception + msg = import_name + name = "" + tracked = [] + for part in import_name.replace(":", ".").split("."): + name = f"{name}.{part}" if name else part + imported = import_string(name, silent=True) + if imported: + tracked.append((name, getattr(imported, "__file__", None))) + else: + track = [f"- {n!r} found in {i!r}." for n, i in tracked] + track.append(f"- {name!r} not found.") + track_str = "\n".join(track) + msg = ( + f"import_string() failed for {import_name!r}. Possible reasons" + f" are:\n\n" + "- missing __init__.py in a package;\n" + "- package or module path not included in sys.path;\n" + "- duplicated package or module name taking precedence in" + " sys.path;\n" + "- missing module, class, function or variable;\n\n" + f"Debugged import:\n\n{track_str}\n\n" + f"Original exception:\n\n{type(exception).__name__}: {exception}" + ) + break + + super().__init__(msg) + + def __repr__(self) -> str: + return f"<{type(self).__name__}({self.import_name!r}, {self.exception!r})>" diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py new file mode 100644 index 0000000..b8c45d7 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py @@ -0,0 +1,3 @@ +from .request import Request as Request +from .response import Response as Response +from .response import ResponseStream diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/request.py b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/request.py new file mode 100644 index 0000000..57b739c --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/request.py @@ -0,0 +1,614 @@ +import functools +import json +import typing +import typing as t +from io import BytesIO + +from .._internal import _wsgi_decoding_dance +from ..datastructures import CombinedMultiDict +from ..datastructures import EnvironHeaders +from ..datastructures import FileStorage +from ..datastructures import ImmutableMultiDict +from ..datastructures import iter_multi_items +from ..datastructures import MultiDict +from ..formparser import default_stream_factory +from ..formparser import FormDataParser +from ..sansio.request import Request as _SansIORequest +from ..utils import cached_property +from ..utils import environ_property +from ..wsgi import _get_server +from ..wsgi import get_input_stream +from werkzeug.exceptions import BadRequest + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class Request(_SansIORequest): + """Represents an incoming WSGI HTTP request, with headers and body + taken from the WSGI environment. Has properties and methods for + using the functionality defined by various HTTP specs. The data in + requests object is read-only. + + Text data is assumed to use UTF-8 encoding, which should be true for + the vast majority of modern clients. Using an encoding set by the + client is unsafe in Python due to extra encodings it provides, such + as ``zip``. To change the assumed encoding, subclass and replace + :attr:`charset`. + + :param environ: The WSGI environ is generated by the WSGI server and + contains information about the server configuration and client + request. + :param populate_request: Add this request object to the WSGI environ + as ``environ['werkzeug.request']``. Can be useful when + debugging. + :param shallow: Makes reading from :attr:`stream` (and any method + that would read from it) raise a :exc:`RuntimeError`. Useful to + prevent consuming the form data in middleware, which would make + it unavailable to the final application. + + .. versionchanged:: 2.1 + Remove the ``disable_data_descriptor`` attribute. + + .. versionchanged:: 2.0 + Combine ``BaseRequest`` and mixins into a single ``Request`` + class. Using the old classes is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + Read-only mode is enforced with immutable classes for all data. + """ + + #: the maximum content length. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: parsing fails because more than the specified value is transmitted + #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :doc:`/request_data` for more details. + #: + #: .. versionadded:: 0.5 + max_content_length: t.Optional[int] = None + + #: the maximum form field size. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: data in memory for post data is longer than the specified value a + #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :doc:`/request_data` for more details. + #: + #: .. versionadded:: 0.5 + max_form_memory_size: t.Optional[int] = None + + #: The form data parser that should be used. Can be replaced to customize + #: the form date parsing. + form_data_parser_class: t.Type[FormDataParser] = FormDataParser + + #: The WSGI environment containing HTTP headers and information from + #: the WSGI server. + environ: "WSGIEnvironment" + + #: Set when creating the request object. If ``True``, reading from + #: the request body will cause a ``RuntimeException``. Useful to + #: prevent modifying the stream from middleware. + shallow: bool + + def __init__( + self, + environ: "WSGIEnvironment", + populate_request: bool = True, + shallow: bool = False, + ) -> None: + super().__init__( + method=environ.get("REQUEST_METHOD", "GET"), + scheme=environ.get("wsgi.url_scheme", "http"), + server=_get_server(environ), + root_path=_wsgi_decoding_dance( + environ.get("SCRIPT_NAME") or "", self.charset, self.encoding_errors + ), + path=_wsgi_decoding_dance( + environ.get("PATH_INFO") or "", self.charset, self.encoding_errors + ), + query_string=environ.get("QUERY_STRING", "").encode("latin1"), + headers=EnvironHeaders(environ), + remote_addr=environ.get("REMOTE_ADDR"), + ) + self.environ = environ + self.shallow = shallow + + if populate_request and not shallow: + self.environ["werkzeug.request"] = self + + @classmethod + def from_values(cls, *args: t.Any, **kwargs: t.Any) -> "Request": + """Create a new request object based on the values provided. If + environ is given missing values are filled from there. This method is + useful for small scripts when you need to simulate a request from an URL. + Do not use this method for unittesting, there is a full featured client + object (:class:`Client`) that allows to create multipart requests, + support for cookies etc. + + This accepts the same options as the + :class:`~werkzeug.test.EnvironBuilder`. + + .. versionchanged:: 0.5 + This method now accepts the same arguments as + :class:`~werkzeug.test.EnvironBuilder`. Because of this the + `environ` parameter is now called `environ_overrides`. + + :return: request object + """ + from ..test import EnvironBuilder + + charset = kwargs.pop("charset", cls.charset) + kwargs["charset"] = charset + builder = EnvironBuilder(*args, **kwargs) + try: + return builder.get_request(cls) + finally: + builder.close() + + @classmethod + def application( + cls, f: t.Callable[["Request"], "WSGIApplication"] + ) -> "WSGIApplication": + """Decorate a function as responder that accepts the request as + the last argument. This works like the :func:`responder` + decorator but the function is passed the request object as the + last argument and the request object will be closed + automatically:: + + @Request.application + def my_wsgi_app(request): + return Response('Hello World!') + + As of Werkzeug 0.14 HTTP exceptions are automatically caught and + converted to responses instead of failing. + + :param f: the WSGI callable to decorate + :return: a new WSGI callable + """ + #: return a callable that wraps the -2nd argument with the request + #: and calls the function with all the arguments up to that one and + #: the request. The return value is then called with the latest + #: two arguments. This makes it possible to use this decorator for + #: both standalone WSGI functions as well as bound methods and + #: partially applied functions. + from ..exceptions import HTTPException + + @functools.wraps(f) + def application(*args): # type: ignore + request = cls(args[-2]) + with request: + try: + resp = f(*args[:-2] + (request,)) + except HTTPException as e: + resp = e.get_response(args[-2]) + return resp(*args[-2:]) + + return t.cast("WSGIApplication", application) + + def _get_file_stream( + self, + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str] = None, + content_length: t.Optional[int] = None, + ) -> t.IO[bytes]: + """Called to get a stream for the file upload. + + This must provide a file-like class with `read()`, `readline()` + and `seek()` methods that is both writeable and readable. + + The default implementation returns a temporary file if the total + content length is higher than 500KB. Because many browsers do not + provide a content length for the files only the total content + length matters. + + :param total_content_length: the total content length of all the + data in the request combined. This value + is guaranteed to be there. + :param content_type: the mimetype of the uploaded file. + :param filename: the filename of the uploaded file. May be `None`. + :param content_length: the length of this file. This value is usually + not provided because webbrowsers do not provide + this value. + """ + return default_stream_factory( + total_content_length=total_content_length, + filename=filename, + content_type=content_type, + content_length=content_length, + ) + + @property + def want_form_data_parsed(self) -> bool: + """``True`` if the request method carries content. By default + this is true if a ``Content-Type`` is sent. + + .. versionadded:: 0.8 + """ + return bool(self.environ.get("CONTENT_TYPE")) + + def make_form_data_parser(self) -> FormDataParser: + """Creates the form data parser. Instantiates the + :attr:`form_data_parser_class` with some parameters. + + .. versionadded:: 0.8 + """ + return self.form_data_parser_class( + self._get_file_stream, + self.charset, + self.encoding_errors, + self.max_form_memory_size, + self.max_content_length, + self.parameter_storage_class, + ) + + def _load_form_data(self) -> None: + """Method used internally to retrieve submitted data. After calling + this sets `form` and `files` on the request object to multi dicts + filled with the incoming form data. As a matter of fact the input + stream will be empty afterwards. You can also call this method to + force the parsing of the form data. + + .. versionadded:: 0.8 + """ + # abort early if we have already consumed the stream + if "form" in self.__dict__: + return + + if self.want_form_data_parsed: + parser = self.make_form_data_parser() + data = parser.parse( + self._get_stream_for_parsing(), + self.mimetype, + self.content_length, + self.mimetype_params, + ) + else: + data = ( + self.stream, + self.parameter_storage_class(), + self.parameter_storage_class(), + ) + + # inject the values into the instance dict so that we bypass + # our cached_property non-data descriptor. + d = self.__dict__ + d["stream"], d["form"], d["files"] = data + + def _get_stream_for_parsing(self) -> t.IO[bytes]: + """This is the same as accessing :attr:`stream` with the difference + that if it finds cached data from calling :meth:`get_data` first it + will create a new stream out of the cached data. + + .. versionadded:: 0.9.3 + """ + cached_data = getattr(self, "_cached_data", None) + if cached_data is not None: + return BytesIO(cached_data) + return self.stream + + def close(self) -> None: + """Closes associated resources of this request object. This + closes all file handles explicitly. You can also use the request + object in a with statement which will automatically close it. + + .. versionadded:: 0.9 + """ + files = self.__dict__.get("files") + for _key, value in iter_multi_items(files or ()): + value.close() + + def __enter__(self) -> "Request": + return self + + def __exit__(self, exc_type, exc_value, tb) -> None: # type: ignore + self.close() + + @cached_property + def stream(self) -> t.IO[bytes]: + """ + If the incoming form data was not encoded with a known mimetype + the data is stored unmodified in this stream for consumption. Most + of the time it is a better idea to use :attr:`data` which will give + you that data as a string. The stream only returns the data once. + + Unlike :attr:`input_stream` this stream is properly guarded that you + can't accidentally read past the length of the input. Werkzeug will + internally always refer to this stream to read data which makes it + possible to wrap this object with a stream that does filtering. + + .. versionchanged:: 0.9 + This stream is now always available but might be consumed by the + form parser later on. Previously the stream was only set if no + parsing happened. + """ + if self.shallow: + raise RuntimeError( + "This request was created with 'shallow=True', reading" + " from the input stream is disabled." + ) + + return get_input_stream(self.environ) + + input_stream = environ_property[t.IO[bytes]]( + "wsgi.input", + doc="""The WSGI input stream. + + In general it's a bad idea to use this one because you can + easily read past the boundary. Use the :attr:`stream` + instead.""", + ) + + @cached_property + def data(self) -> bytes: + """ + Contains the incoming request data as string in case it came with + a mimetype Werkzeug does not handle. + """ + return self.get_data(parse_form_data=True) + + @typing.overload + def get_data( # type: ignore + self, + cache: bool = True, + as_text: "te.Literal[False]" = False, + parse_form_data: bool = False, + ) -> bytes: + ... + + @typing.overload + def get_data( + self, + cache: bool = True, + as_text: "te.Literal[True]" = ..., + parse_form_data: bool = False, + ) -> str: + ... + + def get_data( + self, cache: bool = True, as_text: bool = False, parse_form_data: bool = False + ) -> t.Union[bytes, str]: + """This reads the buffered incoming data from the client into one + bytes object. By default this is cached but that behavior can be + changed by setting `cache` to `False`. + + Usually it's a bad idea to call this method without checking the + content length first as a client could send dozens of megabytes or more + to cause memory problems on the server. + + Note that if the form data was already parsed this method will not + return anything as form data parsing does not cache the data like + this method does. To implicitly invoke form data parsing function + set `parse_form_data` to `True`. When this is done the return value + of this method will be an empty string if the form parser handles + the data. This generally is not necessary as if the whole data is + cached (which is the default) the form parser will used the cached + data to parse the form data. Please be generally aware of checking + the content length first in any case before calling this method + to avoid exhausting server memory. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + rv = getattr(self, "_cached_data", None) + if rv is None: + if parse_form_data: + self._load_form_data() + rv = self.stream.read() + if cache: + self._cached_data = rv + if as_text: + rv = rv.decode(self.charset, self.encoding_errors) + return rv + + @cached_property + def form(self) -> "ImmutableMultiDict[str, str]": + """The form parameters. By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + + Please keep in mind that file uploads will not end up here, but instead + in the :attr:`files` attribute. + + .. versionchanged:: 0.9 + + Previous to Werkzeug 0.9 this would only contain form data for POST + and PUT requests. + """ + self._load_form_data() + return self.form + + @cached_property + def values(self) -> "CombinedMultiDict[str, str]": + """A :class:`werkzeug.datastructures.CombinedMultiDict` that + combines :attr:`args` and :attr:`form`. + + For GET requests, only ``args`` are present, not ``form``. + + .. versionchanged:: 2.0 + For GET requests, only ``args`` are present, not ``form``. + """ + sources = [self.args] + + if self.method != "GET": + # GET requests can have a body, and some caching proxies + # might not treat that differently than a normal GET + # request, allowing form data to "invisibly" affect the + # cache without indication in the query string / URL. + sources.append(self.form) + + args = [] + + for d in sources: + if not isinstance(d, MultiDict): + d = MultiDict(d) + + args.append(d) + + return CombinedMultiDict(args) + + @cached_property + def files(self) -> "ImmutableMultiDict[str, FileStorage]": + """:class:`~werkzeug.datastructures.MultiDict` object containing + all uploaded files. Each key in :attr:`files` is the name from the + ````. Each value in :attr:`files` is a + Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. + + It basically behaves like a standard file object you know from Python, + with the difference that it also has a + :meth:`~werkzeug.datastructures.FileStorage.save` function that can + store the file on the filesystem. + + Note that :attr:`files` will only contain data if the request method was + POST, PUT or PATCH and the ``

    `` that posted to the request had + ``enctype="multipart/form-data"``. It will be empty otherwise. + + See the :class:`~werkzeug.datastructures.MultiDict` / + :class:`~werkzeug.datastructures.FileStorage` documentation for + more details about the used data structure. + """ + self._load_form_data() + return self.files + + @property + def script_root(self) -> str: + """Alias for :attr:`self.root_path`. ``environ["SCRIPT_ROOT"]`` + without a trailing slash. + """ + return self.root_path + + @cached_property + def url_root(self) -> str: + """Alias for :attr:`root_url`. The URL with scheme, host, and + root path. For example, ``https://example.com/app/``. + """ + return self.root_url + + remote_user = environ_property[str]( + "REMOTE_USER", + doc="""If the server supports user authentication, and the + script is protected, this attribute contains the username the + user has authenticated as.""", + ) + is_multithread = environ_property[bool]( + "wsgi.multithread", + doc="""boolean that is `True` if the application is served by a + multithreaded WSGI server.""", + ) + is_multiprocess = environ_property[bool]( + "wsgi.multiprocess", + doc="""boolean that is `True` if the application is served by a + WSGI server that spawns multiple processes.""", + ) + is_run_once = environ_property[bool]( + "wsgi.run_once", + doc="""boolean that is `True` if the application will be + executed only once in a process lifetime. This is the case for + CGI for example, but it's not guaranteed that the execution only + happens one time.""", + ) + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Optional[t.Any]: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + + If the request content type is not ``application/json``, this + will raise a 400 Bad Request error. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + return self.get_json() + + # Cached values for ``(silent=False, silent=True)``. Initialized + # with sentinel values. + _cached_json: t.Tuple[t.Any, t.Any] = (Ellipsis, Ellipsis) + + def get_json( + self, force: bool = False, silent: bool = False, cache: bool = True + ) -> t.Optional[t.Any]: + """Parse :attr:`data` as JSON. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), or parsing + fails, :meth:`on_json_loading_failed` is called and + its return value is used as the return value. By default this + raises a 400 Bad Request error. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence mimetype and parsing errors, and + return ``None`` instead. + :param cache: Store the parsed JSON to return for subsequent + calls. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + if cache and self._cached_json[silent] is not Ellipsis: + return self._cached_json[silent] + + if not (force or self.is_json): + if not silent: + return self.on_json_loading_failed(None) + else: + return None + + data = self.get_data(cache=cache) + + try: + rv = self.json_module.loads(data) + except ValueError as e: + if silent: + rv = None + + if cache: + normal_rv, _ = self._cached_json + self._cached_json = (normal_rv, rv) + else: + rv = self.on_json_loading_failed(e) + + if cache: + _, silent_rv = self._cached_json + self._cached_json = (rv, silent_rv) + else: + if cache: + self._cached_json = (rv, rv) + + return rv + + def on_json_loading_failed(self, e: t.Optional[ValueError]) -> t.Any: + """Called if :meth:`get_json` fails and isn't silenced. + + If this method returns a value, it is used as the return value + for :meth:`get_json`. The default implementation raises + :exc:`~werkzeug.exceptions.BadRequest`. + + :param e: If parsing failed, this is the exception. It will be + ``None`` if the content type wasn't ``application/json``. + """ + if e is not None: + raise BadRequest(f"Failed to decode JSON object: {e}") + + raise BadRequest( + "Did not attempt to load JSON data because the request" + " Content-Type was not 'application/json'." + ) diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/response.py b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/response.py new file mode 100644 index 0000000..7e888cb --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/wrappers/response.py @@ -0,0 +1,877 @@ +import json +import typing +import typing as t +import warnings +from http import HTTPStatus + +from .._internal import _to_bytes +from ..datastructures import Headers +from ..http import remove_entity_headers +from ..sansio.response import Response as _SansIOResponse +from ..urls import iri_to_uri +from ..urls import url_join +from ..utils import cached_property +from ..wsgi import ClosingIterator +from ..wsgi import get_current_url +from werkzeug._internal import _get_environ +from werkzeug.http import generate_etag +from werkzeug.http import http_date +from werkzeug.http import is_resource_modified +from werkzeug.http import parse_etags +from werkzeug.http import parse_range_header +from werkzeug.wsgi import _RangeWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from .request import Request + + +def _warn_if_string(iterable: t.Iterable) -> None: + """Helper for the response objects to check if the iterable returned + to the WSGI server is not a string. + """ + if isinstance(iterable, str): + warnings.warn( + "Response iterable was set to a string. This will appear to" + " work but means that the server will send the data to the" + " client one character at a time. This is almost never" + " intended behavior, use 'response.data' to assign strings" + " to the response object.", + stacklevel=2, + ) + + +def _iter_encoded( + iterable: t.Iterable[t.Union[str, bytes]], charset: str +) -> t.Iterator[bytes]: + for item in iterable: + if isinstance(item, str): + yield item.encode(charset) + else: + yield item + + +def _clean_accept_ranges(accept_ranges: t.Union[bool, str]) -> str: + if accept_ranges is True: + return "bytes" + elif accept_ranges is False: + return "none" + elif isinstance(accept_ranges, str): + return accept_ranges + raise ValueError("Invalid accept_ranges value") + + +class Response(_SansIOResponse): + """Represents an outgoing WSGI HTTP response with body, status, and + headers. Has properties and methods for using the functionality + defined by various HTTP specs. + + The response body is flexible to support different use cases. The + simple form is passing bytes, or a string which will be encoded as + UTF-8. Passing an iterable of bytes or strings makes this a + streaming response. A generator is particularly useful for building + a CSV file in memory or using SSE (Server Sent Events). A file-like + object is also iterable, although the + :func:`~werkzeug.utils.send_file` helper should be used in that + case. + + The response object is itself a WSGI application callable. When + called (:meth:`__call__`) with ``environ`` and ``start_response``, + it will pass its status and headers to ``start_response`` then + return its body as an iterable. + + .. code-block:: python + + from werkzeug.wrappers.response import Response + + def index(): + return Response("Hello, World!") + + def application(environ, start_response): + path = environ.get("PATH_INFO") or "/" + + if path == "/": + response = index() + else: + response = Response("Not Found", status=404) + + return response(environ, start_response) + + :param response: The data for the body of the response. A string or + bytes, or tuple or list of strings or bytes, for a fixed-length + response, or any other iterable of strings or bytes for a + streaming response. Defaults to an empty body. + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + :param direct_passthrough: Pass the response body directly through + as the WSGI iterable. This can be used when the body is a binary + file or other iterator of bytes, to skip some unnecessary + checks. Use :func:`~werkzeug.utils.send_file` instead of setting + this manually. + + .. versionchanged:: 2.0 + Combine ``BaseResponse`` and mixins into a single ``Response`` + class. Using the old classes is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + The ``direct_passthrough`` parameter was added. + """ + + #: if set to `False` accessing properties on the response object will + #: not try to consume the response iterator and convert it into a list. + #: + #: .. versionadded:: 0.6.2 + #: + #: That attribute was previously called `implicit_seqence_conversion`. + #: (Notice the typo). If you did use this feature, you have to adapt + #: your code to the name change. + implicit_sequence_conversion = True + + #: If a redirect ``Location`` header is a relative URL, make it an + #: absolute URL, including scheme and domain. + #: + #: .. versionchanged:: 2.1 + #: This is disabled by default, so responses will send relative + #: redirects. + #: + #: .. versionadded:: 0.8 + autocorrect_location_header = False + + #: Should this response object automatically set the content-length + #: header if possible? This is true by default. + #: + #: .. versionadded:: 0.8 + automatically_set_content_length = True + + #: The response body to send as the WSGI iterable. A list of strings + #: or bytes represents a fixed-length response, any other iterable + #: is a streaming response. Strings are encoded to bytes as UTF-8. + #: + #: Do not set to a plain string or bytes, that will cause sending + #: the response to be very inefficient as it will iterate one byte + #: at a time. + response: t.Union[t.Iterable[str], t.Iterable[bytes]] + + def __init__( + self, + response: t.Optional[ + t.Union[t.Iterable[bytes], bytes, t.Iterable[str], str] + ] = None, + status: t.Optional[t.Union[int, str, HTTPStatus]] = None, + headers: t.Optional[ + t.Union[ + t.Mapping[str, t.Union[str, int, t.Iterable[t.Union[str, int]]]], + t.Iterable[t.Tuple[str, t.Union[str, int]]], + ] + ] = None, + mimetype: t.Optional[str] = None, + content_type: t.Optional[str] = None, + direct_passthrough: bool = False, + ) -> None: + super().__init__( + status=status, + headers=headers, + mimetype=mimetype, + content_type=content_type, + ) + + #: Pass the response body directly through as the WSGI iterable. + #: This can be used when the body is a binary file or other + #: iterator of bytes, to skip some unnecessary checks. Use + #: :func:`~werkzeug.utils.send_file` instead of setting this + #: manually. + self.direct_passthrough = direct_passthrough + self._on_close: t.List[t.Callable[[], t.Any]] = [] + + # we set the response after the headers so that if a class changes + # the charset attribute, the data is set in the correct charset. + if response is None: + self.response = [] + elif isinstance(response, (str, bytes, bytearray)): + self.set_data(response) + else: + self.response = response + + def call_on_close(self, func: t.Callable[[], t.Any]) -> t.Callable[[], t.Any]: + """Adds a function to the internal list of functions that should + be called as part of closing down the response. Since 0.7 this + function also returns the function that was passed so that this + can be used as a decorator. + + .. versionadded:: 0.6 + """ + self._on_close.append(func) + return func + + def __repr__(self) -> str: + if self.is_sequence: + body_info = f"{sum(map(len, self.iter_encoded()))} bytes" + else: + body_info = "streamed" if self.is_streamed else "likely-streamed" + return f"<{type(self).__name__} {body_info} [{self.status}]>" + + @classmethod + def force_type( + cls, response: "Response", environ: t.Optional["WSGIEnvironment"] = None + ) -> "Response": + """Enforce that the WSGI response is a response object of the current + type. Werkzeug will use the :class:`Response` internally in many + situations like the exceptions. If you call :meth:`get_response` on an + exception you will get back a regular :class:`Response` object, even + if you are using a custom subclass. + + This method can enforce a given response type, and it will also + convert arbitrary WSGI callables into response objects if an environ + is provided:: + + # convert a Werkzeug response object into an instance of the + # MyResponseClass subclass. + response = MyResponseClass.force_type(response) + + # convert any WSGI application into a response object + response = MyResponseClass.force_type(response, environ) + + This is especially useful if you want to post-process responses in + the main dispatcher and use functionality provided by your subclass. + + Keep in mind that this will modify response objects in place if + possible! + + :param response: a response object or wsgi application. + :param environ: a WSGI environment object. + :return: a response object. + """ + if not isinstance(response, Response): + if environ is None: + raise TypeError( + "cannot convert WSGI application into response" + " objects without an environ" + ) + + from ..test import run_wsgi_app + + response = Response(*run_wsgi_app(response, environ)) + + response.__class__ = cls + return response + + @classmethod + def from_app( + cls, app: "WSGIApplication", environ: "WSGIEnvironment", buffered: bool = False + ) -> "Response": + """Create a new response object from an application output. This + works best if you pass it an application that returns a generator all + the time. Sometimes applications may use the `write()` callable + returned by the `start_response` function. This tries to resolve such + edge cases automatically. But if you don't get the expected output + you should set `buffered` to `True` which enforces buffering. + + :param app: the WSGI application to execute. + :param environ: the WSGI environment to execute against. + :param buffered: set to `True` to enforce buffering. + :return: a response object. + """ + from ..test import run_wsgi_app + + return cls(*run_wsgi_app(app, environ, buffered)) + + @typing.overload + def get_data(self, as_text: "te.Literal[False]" = False) -> bytes: + ... + + @typing.overload + def get_data(self, as_text: "te.Literal[True]") -> str: + ... + + def get_data(self, as_text: bool = False) -> t.Union[bytes, str]: + """The string representation of the response body. Whenever you call + this property the response iterable is encoded and flattened. This + can lead to unwanted behavior if you stream big data. + + This behavior can be disabled by setting + :attr:`implicit_sequence_conversion` to `False`. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + self._ensure_sequence() + rv = b"".join(self.iter_encoded()) + + if as_text: + return rv.decode(self.charset) + + return rv + + def set_data(self, value: t.Union[bytes, str]) -> None: + """Sets a new string as response. The value must be a string or + bytes. If a string is set it's encoded to the charset of the + response (utf-8 by default). + + .. versionadded:: 0.9 + """ + # if a string is set, it's encoded directly so that we + # can set the content length + if isinstance(value, str): + value = value.encode(self.charset) + else: + value = bytes(value) + self.response = [value] + if self.automatically_set_content_length: + self.headers["Content-Length"] = str(len(value)) + + data = property( + get_data, + set_data, + doc="A descriptor that calls :meth:`get_data` and :meth:`set_data`.", + ) + + def calculate_content_length(self) -> t.Optional[int]: + """Returns the content length if available or `None` otherwise.""" + try: + self._ensure_sequence() + except RuntimeError: + return None + return sum(len(x) for x in self.iter_encoded()) + + def _ensure_sequence(self, mutable: bool = False) -> None: + """This method can be called by methods that need a sequence. If + `mutable` is true, it will also ensure that the response sequence + is a standard Python list. + + .. versionadded:: 0.6 + """ + if self.is_sequence: + # if we need a mutable object, we ensure it's a list. + if mutable and not isinstance(self.response, list): + self.response = list(self.response) # type: ignore + return + if self.direct_passthrough: + raise RuntimeError( + "Attempted implicit sequence conversion but the" + " response object is in direct passthrough mode." + ) + if not self.implicit_sequence_conversion: + raise RuntimeError( + "The response object required the iterable to be a" + " sequence, but the implicit conversion was disabled." + " Call make_sequence() yourself." + ) + self.make_sequence() + + def make_sequence(self) -> None: + """Converts the response iterator in a list. By default this happens + automatically if required. If `implicit_sequence_conversion` is + disabled, this method is not automatically called and some properties + might raise exceptions. This also encodes all the items. + + .. versionadded:: 0.6 + """ + if not self.is_sequence: + # if we consume an iterable we have to ensure that the close + # method of the iterable is called if available when we tear + # down the response + close = getattr(self.response, "close", None) + self.response = list(self.iter_encoded()) + if close is not None: + self.call_on_close(close) + + def iter_encoded(self) -> t.Iterator[bytes]: + """Iter the response encoded with the encoding of the response. + If the response object is invoked as WSGI application the return + value of this method is used as application iterator unless + :attr:`direct_passthrough` was activated. + """ + if __debug__: + _warn_if_string(self.response) + # Encode in a separate function so that self.response is fetched + # early. This allows us to wrap the response with the return + # value from get_app_iter or iter_encoded. + return _iter_encoded(self.response, self.charset) + + @property + def is_streamed(self) -> bool: + """If the response is streamed (the response is not an iterable with + a length information) this property is `True`. In this case streamed + means that there is no information about the number of iterations. + This is usually `True` if a generator is passed to the response object. + + This is useful for checking before applying some sort of post + filtering that should not take place for streamed responses. + """ + try: + len(self.response) # type: ignore + except (TypeError, AttributeError): + return True + return False + + @property + def is_sequence(self) -> bool: + """If the iterator is buffered, this property will be `True`. A + response object will consider an iterator to be buffered if the + response attribute is a list or tuple. + + .. versionadded:: 0.6 + """ + return isinstance(self.response, (tuple, list)) + + def close(self) -> None: + """Close the wrapped response if possible. You can also use the object + in a with statement which will automatically close it. + + .. versionadded:: 0.9 + Can now be used in a with statement. + """ + if hasattr(self.response, "close"): + self.response.close() # type: ignore + for func in self._on_close: + func() + + def __enter__(self) -> "Response": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close() + + def freeze(self) -> None: + """Make the response object ready to be pickled. Does the + following: + + * Buffer the response into a list, ignoring + :attr:`implicity_sequence_conversion` and + :attr:`direct_passthrough`. + * Set the ``Content-Length`` header. + * Generate an ``ETag`` header if one is not already set. + + .. versionchanged:: 2.1 + Removed the ``no_etag`` parameter. + + .. versionchanged:: 2.0 + An ``ETag`` header is added, the ``no_etag`` parameter is + deprecated and will be removed in Werkzeug 2.1. + + .. versionchanged:: 0.6 + The ``Content-Length`` header is set. + """ + # Always freeze the encoded response body, ignore + # implicit_sequence_conversion and direct_passthrough. + self.response = list(self.iter_encoded()) + self.headers["Content-Length"] = str(sum(map(len, self.response))) + self.add_etag() + + def get_wsgi_headers(self, environ: "WSGIEnvironment") -> Headers: + """This is automatically called right before the response is started + and returns headers modified for the given environment. It returns a + copy of the headers from the response with some modifications applied + if necessary. + + For example the location header (if present) is joined with the root + URL of the environment. Also the content length is automatically set + to zero here for certain status codes. + + .. versionchanged:: 0.6 + Previously that function was called `fix_headers` and modified + the response object in place. Also since 0.6, IRIs in location + and content-location headers are handled properly. + + Also starting with 0.6, Werkzeug will attempt to set the content + length if it is able to figure it out on its own. This is the + case if all the strings in the response iterable are already + encoded and the iterable is buffered. + + :param environ: the WSGI environment of the request. + :return: returns a new :class:`~werkzeug.datastructures.Headers` + object. + """ + headers = Headers(self.headers) + location: t.Optional[str] = None + content_location: t.Optional[str] = None + content_length: t.Optional[t.Union[str, int]] = None + status = self.status_code + + # iterate over the headers to find all values in one go. Because + # get_wsgi_headers is used each response that gives us a tiny + # speedup. + for key, value in headers: + ikey = key.lower() + if ikey == "location": + location = value + elif ikey == "content-location": + content_location = value + elif ikey == "content-length": + content_length = value + + # make sure the location header is an absolute URL + if location is not None: + old_location = location + if isinstance(location, str): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + location = iri_to_uri(location, safe_conversion=True) + + if self.autocorrect_location_header: + current_url = get_current_url(environ, strip_querystring=True) + if isinstance(current_url, str): + current_url = iri_to_uri(current_url) + location = url_join(current_url, location) + if location != old_location: + headers["Location"] = location + + # make sure the content location is a URL + if content_location is not None and isinstance(content_location, str): + headers["Content-Location"] = iri_to_uri(content_location) + + if 100 <= status < 200 or status == 204: + # Per section 3.3.2 of RFC 7230, "a server MUST NOT send a + # Content-Length header field in any response with a status + # code of 1xx (Informational) or 204 (No Content)." + headers.remove("Content-Length") + elif status == 304: + remove_entity_headers(headers) + + # if we can determine the content length automatically, we + # should try to do that. But only if this does not involve + # flattening the iterator or encoding of strings in the + # response. We however should not do that if we have a 304 + # response. + if ( + self.automatically_set_content_length + and self.is_sequence + and content_length is None + and status not in (204, 304) + and not (100 <= status < 200) + ): + try: + content_length = sum(len(_to_bytes(x, "ascii")) for x in self.response) + except UnicodeError: + # Something other than bytes, can't safely figure out + # the length of the response. + pass + else: + headers["Content-Length"] = str(content_length) + + return headers + + def get_app_iter(self, environ: "WSGIEnvironment") -> t.Iterable[bytes]: + """Returns the application iterator for the given environ. Depending + on the request method and the current status code the return value + might be an empty response rather than the one from the response. + + If the request method is `HEAD` or the status code is in a range + where the HTTP specification requires an empty response, an empty + iterable is returned. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: a response iterable. + """ + status = self.status_code + if ( + environ["REQUEST_METHOD"] == "HEAD" + or 100 <= status < 200 + or status in (204, 304) + ): + iterable: t.Iterable[bytes] = () + elif self.direct_passthrough: + if __debug__: + _warn_if_string(self.response) + return self.response # type: ignore + else: + iterable = self.iter_encoded() + return ClosingIterator(iterable, self.close) + + def get_wsgi_response( + self, environ: "WSGIEnvironment" + ) -> t.Tuple[t.Iterable[bytes], str, t.List[t.Tuple[str, str]]]: + """Returns the final WSGI response as tuple. The first item in + the tuple is the application iterator, the second the status and + the third the list of headers. The response returned is created + specially for the given environment. For example if the request + method in the WSGI environment is ``'HEAD'`` the response will + be empty and only the headers and status code will be present. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: an ``(app_iter, status, headers)`` tuple. + """ + headers = self.get_wsgi_headers(environ) + app_iter = self.get_app_iter(environ) + return app_iter, self.status, headers.to_wsgi_list() + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Process this response as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + :return: an application iterator + """ + app_iter, status, headers = self.get_wsgi_response(environ) + start_response(status, headers) + return app_iter + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Optional[t.Any]: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + """ + return self.get_json() + + def get_json(self, force: bool = False, silent: bool = False) -> t.Optional[t.Any]: + """Parse :attr:`data` as JSON. Useful during testing. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), this + returns ``None``. + + Unlike :meth:`Request.get_json`, the result is not cached. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence parsing errors and return ``None`` + instead. + """ + if not (force or self.is_json): + return None + + data = self.get_data() + + try: + return self.json_module.loads(data) + except ValueError: + if not silent: + raise + + return None + + # Stream + + @cached_property + def stream(self) -> "ResponseStream": + """The response iterable as write-only stream.""" + return ResponseStream(self) + + def _wrap_range_response(self, start: int, length: int) -> None: + """Wrap existing Response in case of Range Request context.""" + if self.status_code == 206: + self.response = _RangeWrapper(self.response, start, length) # type: ignore + + def _is_range_request_processable(self, environ: "WSGIEnvironment") -> bool: + """Return ``True`` if `Range` header is present and if underlying + resource is considered unchanged when compared with `If-Range` header. + """ + return ( + "HTTP_IF_RANGE" not in environ + or not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ignore_if_range=False, + ) + ) and "HTTP_RANGE" in environ + + def _process_range_request( + self, + environ: "WSGIEnvironment", + complete_length: t.Optional[int] = None, + accept_ranges: t.Optional[t.Union[bool, str]] = None, + ) -> bool: + """Handle Range Request related headers (RFC7233). If `Accept-Ranges` + header is valid, and Range Request is processable, we set the headers + as described by the RFC, and wrap the underlying response in a + RangeWrapper. + + Returns ``True`` if Range Request can be fulfilled, ``False`` otherwise. + + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Returns ``False`` if the length is 0. + """ + from ..exceptions import RequestedRangeNotSatisfiable + + if ( + accept_ranges is None + or complete_length is None + or complete_length == 0 + or not self._is_range_request_processable(environ) + ): + return False + + parsed_range = parse_range_header(environ.get("HTTP_RANGE")) + + if parsed_range is None: + raise RequestedRangeNotSatisfiable(complete_length) + + range_tuple = parsed_range.range_for_length(complete_length) + content_range_header = parsed_range.to_content_range_header(complete_length) + + if range_tuple is None or content_range_header is None: + raise RequestedRangeNotSatisfiable(complete_length) + + content_length = range_tuple[1] - range_tuple[0] + self.headers["Content-Length"] = content_length + self.headers["Accept-Ranges"] = accept_ranges + self.content_range = content_range_header # type: ignore + self.status_code = 206 + self._wrap_range_response(range_tuple[0], content_length) + return True + + def make_conditional( + self, + request_or_environ: t.Union["WSGIEnvironment", "Request"], + accept_ranges: t.Union[bool, str] = False, + complete_length: t.Optional[int] = None, + ) -> "Response": + """Make the response conditional to the request. This method works + best if an etag was defined for the response already. The `add_etag` + method can be used to do that. If called without etag just the date + header is set. + + This does nothing if the request method in the request or environ is + anything but GET or HEAD. + + For optimal performance when handling range requests, it's recommended + that your response data object implements `seekable`, `seek` and `tell` + methods as described by :py:class:`io.IOBase`. Objects returned by + :meth:`~werkzeug.wsgi.wrap_file` automatically implement those methods. + + It does not remove the body of the response because that's something + the :meth:`__call__` function does for us automatically. + + Returns self so that you can do ``return resp.make_conditional(req)`` + but modifies the object in-place. + + :param request_or_environ: a request object or WSGI environment to be + used to make the response conditional + against. + :param accept_ranges: This parameter dictates the value of + `Accept-Ranges` header. If ``False`` (default), + the header is not set. If ``True``, it will be set + to ``"bytes"``. If ``None``, it will be set to + ``"none"``. If it's a string, it will use this + value. + :param complete_length: Will be used only in valid Range Requests. + It will set `Content-Range` complete length + value and compute `Content-Length` real value. + This parameter is mandatory for successful + Range Requests completion. + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Range processing is skipped if length is 0 instead of + raising a 416 Range Not Satisfiable error. + """ + environ = _get_environ(request_or_environ) + if environ["REQUEST_METHOD"] in ("GET", "HEAD"): + # if the date is not in the headers, add it now. We however + # will not override an already existing header. Unfortunately + # this header will be overridden by many WSGI servers including + # wsgiref. + if "date" not in self.headers: + self.headers["Date"] = http_date() + accept_ranges = _clean_accept_ranges(accept_ranges) + is206 = self._process_range_request(environ, complete_length, accept_ranges) + if not is206 and not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ): + if parse_etags(environ.get("HTTP_IF_MATCH")): + self.status_code = 412 + else: + self.status_code = 304 + if ( + self.automatically_set_content_length + and "content-length" not in self.headers + ): + length = self.calculate_content_length() + if length is not None: + self.headers["Content-Length"] = length + return self + + def add_etag(self, overwrite: bool = False, weak: bool = False) -> None: + """Add an etag for the current response if there is none yet. + + .. versionchanged:: 2.0 + SHA-1 is used to generate the value. MD5 may not be + available in some environments. + """ + if overwrite or "etag" not in self.headers: + self.set_etag(generate_etag(self.get_data()), weak) + + +class ResponseStream: + """A file descriptor like object used by :meth:`Response.stream` to + represent the body of the stream. It directly pushes into the + response iterable of the response object. + """ + + mode = "wb+" + + def __init__(self, response: Response): + self.response = response + self.closed = False + + def write(self, value: bytes) -> int: + if self.closed: + raise ValueError("I/O operation on closed file") + self.response._ensure_sequence(mutable=True) + self.response.response.append(value) # type: ignore + self.response.headers.pop("Content-Length", None) + return len(value) + + def writelines(self, seq: t.Iterable[bytes]) -> None: + for item in seq: + self.write(item) + + def close(self) -> None: + self.closed = True + + def flush(self) -> None: + if self.closed: + raise ValueError("I/O operation on closed file") + + def isatty(self) -> bool: + if self.closed: + raise ValueError("I/O operation on closed file") + return False + + def tell(self) -> int: + self.response._ensure_sequence() + return sum(map(len, self.response.response)) + + @property + def encoding(self) -> str: + return self.response.charset diff --git a/axios-example/lib/python3.10/site-packages/werkzeug/wsgi.py b/axios-example/lib/python3.10/site-packages/werkzeug/wsgi.py new file mode 100644 index 0000000..9cfa74d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/werkzeug/wsgi.py @@ -0,0 +1,982 @@ +import io +import re +import typing as t +from functools import partial +from functools import update_wrapper +from itertools import chain + +from ._internal import _make_encode_wrapper +from ._internal import _to_bytes +from ._internal import _to_str +from .sansio import utils as _sansio_utils +from .sansio.utils import host_is_trusted # noqa: F401 # Imported as part of API +from .urls import _URLTuple +from .urls import uri_to_iri +from .urls import url_join +from .urls import url_parse +from .urls import url_quote + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def responder(f: t.Callable[..., "WSGIApplication"]) -> "WSGIApplication": + """Marks a function as responder. Decorate a function with it and it + will automatically call the return value as WSGI application. + + Example:: + + @responder + def application(environ, start_response): + return Response('Hello World!') + """ + return update_wrapper(lambda *a: f(*a)(*a[-2:]), f) + + +def get_current_url( + environ: "WSGIEnvironment", + root_only: bool = False, + strip_querystring: bool = False, + host_only: bool = False, + trusted_hosts: t.Optional[t.Iterable[str]] = None, +) -> str: + """Recreate the URL for a request from the parts in a WSGI + environment. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param environ: The WSGI environment to get the URL parts from. + :param root_only: Only build the root path, don't include the + remaining path or query string. + :param strip_querystring: Don't include the query string. + :param host_only: Only build the scheme and host. + :param trusted_hosts: A list of trusted host names to validate the + host against. + """ + parts = { + "scheme": environ["wsgi.url_scheme"], + "host": get_host(environ, trusted_hosts), + } + + if not host_only: + parts["root_path"] = environ.get("SCRIPT_NAME", "") + + if not root_only: + parts["path"] = environ.get("PATH_INFO", "") + + if not strip_querystring: + parts["query_string"] = environ.get("QUERY_STRING", "").encode("latin1") + + return _sansio_utils.get_current_url(**parts) + + +def _get_server( + environ: "WSGIEnvironment", +) -> t.Optional[t.Tuple[str, t.Optional[int]]]: + name = environ.get("SERVER_NAME") + + if name is None: + return None + + try: + port: t.Optional[int] = int(environ.get("SERVER_PORT", None)) + except (TypeError, ValueError): + # unix socket + port = None + + return name, port + + +def get_host( + environ: "WSGIEnvironment", trusted_hosts: t.Optional[t.Iterable[str]] = None +) -> str: + """Return the host for the given WSGI environment. + + The ``Host`` header is preferred, then ``SERVER_NAME`` if it's not + set. The returned host will only contain the port if it is different + than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param environ: A WSGI environment dict. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + return _sansio_utils.get_host( + environ["wsgi.url_scheme"], + environ.get("HTTP_HOST"), + _get_server(environ), + trusted_hosts, + ) + + +def get_content_length(environ: "WSGIEnvironment") -> t.Optional[int]: + """Returns the content length from the WSGI environment as + integer. If it's not available or chunked transfer encoding is used, + ``None`` is returned. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the content length from. + """ + if environ.get("HTTP_TRANSFER_ENCODING", "") == "chunked": + return None + + content_length = environ.get("CONTENT_LENGTH") + if content_length is not None: + try: + return max(0, int(content_length)) + except (ValueError, TypeError): + pass + return None + + +def get_input_stream( + environ: "WSGIEnvironment", safe_fallback: bool = True +) -> t.IO[bytes]: + """Returns the input stream from the WSGI environment and wraps it + in the most sensible way possible. The stream returned is not the + raw WSGI stream in most cases but one that is safe to read from + without taking into account the content length. + + If content length is not set, the stream will be empty for safety reasons. + If the WSGI server supports chunked or infinite streams, it should set + the ``wsgi.input_terminated`` value in the WSGI environ to indicate that. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the stream from. + :param safe_fallback: use an empty stream as a safe fallback when the + content length is not set. Disabling this allows infinite streams, + which can be a denial-of-service risk. + """ + stream = t.cast(t.IO[bytes], environ["wsgi.input"]) + content_length = get_content_length(environ) + + # A wsgi extension that tells us if the input is terminated. In + # that case we return the stream unchanged as we know we can safely + # read it until the end. + if environ.get("wsgi.input_terminated"): + return stream + + # If the request doesn't specify a content length, returning the stream is + # potentially dangerous because it could be infinite, malicious or not. If + # safe_fallback is true, return an empty stream instead for safety. + if content_length is None: + return io.BytesIO() if safe_fallback else stream + + # Otherwise limit the stream to the content length + return t.cast(t.IO[bytes], LimitedStream(stream, content_length)) + + +def get_query_string(environ: "WSGIEnvironment") -> str: + """Returns the ``QUERY_STRING`` from the WSGI environment. This also + takes care of the WSGI decoding dance. The string returned will be + restricted to ASCII characters. + + :param environ: WSGI environment to get the query string from. + + .. versionadded:: 0.9 + """ + qs = environ.get("QUERY_STRING", "").encode("latin1") + # QUERY_STRING really should be ascii safe but some browsers + # will send us some unicode stuff (I am looking at you IE). + # In that case we want to urllib quote it badly. + return url_quote(qs, safe=":&%=+$!*'(),") + + +def get_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> str: + """Return the ``PATH_INFO`` from the WSGI environment and decode it + unless ``charset`` is ``None``. + + :param environ: WSGI environment to get the path from. + :param charset: The charset for the path info, or ``None`` if no + decoding should be performed. + :param errors: The decoding error handling. + + .. versionadded:: 0.9 + """ + path = environ.get("PATH_INFO", "").encode("latin1") + return _to_str(path, charset, errors, allow_none_charset=True) # type: ignore + + +def get_script_name( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> str: + """Return the ``SCRIPT_NAME`` from the WSGI environment and decode + it unless `charset` is set to ``None``. + + :param environ: WSGI environment to get the path from. + :param charset: The charset for the path, or ``None`` if no decoding + should be performed. + :param errors: The decoding error handling. + + .. versionadded:: 0.9 + """ + path = environ.get("SCRIPT_NAME", "").encode("latin1") + return _to_str(path, charset, errors, allow_none_charset=True) # type: ignore + + +def pop_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> t.Optional[str]: + """Removes and returns the next segment of `PATH_INFO`, pushing it onto + `SCRIPT_NAME`. Returns `None` if there is nothing left on `PATH_INFO`. + + If the `charset` is set to `None` bytes are returned. + + If there are empty segments (``'/foo//bar``) these are ignored but + properly pushed to the `SCRIPT_NAME`: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> pop_path_info(env) + 'a' + >>> env['SCRIPT_NAME'] + '/foo/a' + >>> pop_path_info(env) + 'b' + >>> env['SCRIPT_NAME'] + '/foo/a/b' + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is modified. + :param charset: The ``encoding`` parameter passed to + :func:`bytes.decode`. + :param errors: The ``errors`` paramater passed to + :func:`bytes.decode`. + """ + path = environ.get("PATH_INFO") + if not path: + return None + + script_name = environ.get("SCRIPT_NAME", "") + + # shift multiple leading slashes over + old_path = path + path = path.lstrip("/") + if path != old_path: + script_name += "/" * (len(old_path) - len(path)) + + if "/" not in path: + environ["PATH_INFO"] = "" + environ["SCRIPT_NAME"] = script_name + path + rv = path.encode("latin1") + else: + segment, path = path.split("/", 1) + environ["PATH_INFO"] = f"/{path}" + environ["SCRIPT_NAME"] = script_name + segment + rv = segment.encode("latin1") + + return _to_str(rv, charset, errors, allow_none_charset=True) # type: ignore + + +def peek_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> t.Optional[str]: + """Returns the next segment on the `PATH_INFO` or `None` if there + is none. Works like :func:`pop_path_info` without modifying the + environment: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> peek_path_info(env) + 'a' + >>> peek_path_info(env) + 'a' + + If the `charset` is set to `None` bytes are returned. + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is checked. + """ + segments = environ.get("PATH_INFO", "").lstrip("/").split("/", 1) + if segments: + return _to_str( # type: ignore + segments[0].encode("latin1"), charset, errors, allow_none_charset=True + ) + return None + + +def extract_path_info( + environ_or_baseurl: t.Union[str, "WSGIEnvironment"], + path_or_url: t.Union[str, _URLTuple], + charset: str = "utf-8", + errors: str = "werkzeug.url_quote", + collapse_http_schemes: bool = True, +) -> t.Optional[str]: + """Extracts the path info from the given URL (or WSGI environment) and + path. The path info returned is a string. The URLs might also be IRIs. + + If the path info could not be determined, `None` is returned. + + Some examples: + + >>> extract_path_info('http://example.com/app', '/app/hello') + '/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello') + '/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello', + ... collapse_http_schemes=False) is None + True + + Instead of providing a base URL you can also pass a WSGI environment. + + :param environ_or_baseurl: a WSGI environment dict, a base URL or + base IRI. This is the root of the + application. + :param path_or_url: an absolute path from the server root, a + relative path (in which case it's the path info) + or a full URL. + :param charset: the charset for byte data in URLs + :param errors: the error handling on decode + :param collapse_http_schemes: if set to `False` the algorithm does + not assume that http and https on the + same server point to the same + resource. + + .. versionchanged:: 0.15 + The ``errors`` parameter defaults to leaving invalid bytes + quoted instead of replacing them. + + .. versionadded:: 0.6 + """ + + def _normalize_netloc(scheme: str, netloc: str) -> str: + parts = netloc.split("@", 1)[-1].split(":", 1) + port: t.Optional[str] + + if len(parts) == 2: + netloc, port = parts + if (scheme == "http" and port == "80") or ( + scheme == "https" and port == "443" + ): + port = None + else: + netloc = parts[0] + port = None + + if port is not None: + netloc += f":{port}" + + return netloc + + # make sure whatever we are working on is a IRI and parse it + path = uri_to_iri(path_or_url, charset, errors) + if isinstance(environ_or_baseurl, dict): + environ_or_baseurl = get_current_url(environ_or_baseurl, root_only=True) + base_iri = uri_to_iri(environ_or_baseurl, charset, errors) + base_scheme, base_netloc, base_path = url_parse(base_iri)[:3] + cur_scheme, cur_netloc, cur_path = url_parse(url_join(base_iri, path))[:3] + + # normalize the network location + base_netloc = _normalize_netloc(base_scheme, base_netloc) + cur_netloc = _normalize_netloc(cur_scheme, cur_netloc) + + # is that IRI even on a known HTTP scheme? + if collapse_http_schemes: + for scheme in base_scheme, cur_scheme: + if scheme not in ("http", "https"): + return None + else: + if not (base_scheme in ("http", "https") and base_scheme == cur_scheme): + return None + + # are the netlocs compatible? + if base_netloc != cur_netloc: + return None + + # are we below the application path? + base_path = base_path.rstrip("/") + if not cur_path.startswith(base_path): + return None + + return f"/{cur_path[len(base_path) :].lstrip('/')}" + + +class ClosingIterator: + """The WSGI specification requires that all middlewares and gateways + respect the `close` callback of the iterable returned by the application. + Because it is useful to add another close action to a returned iterable + and adding a custom iterable is a boring task this class can be used for + that:: + + return ClosingIterator(app(environ, start_response), [cleanup_session, + cleanup_locals]) + + If there is just one close function it can be passed instead of the list. + + A closing iterator is not needed if the application uses response objects + and finishes the processing if the response is started:: + + try: + return response(environ, start_response) + finally: + cleanup_session() + cleanup_locals() + """ + + def __init__( + self, + iterable: t.Iterable[bytes], + callbacks: t.Optional[ + t.Union[t.Callable[[], None], t.Iterable[t.Callable[[], None]]] + ] = None, + ) -> None: + iterator = iter(iterable) + self._next = t.cast(t.Callable[[], bytes], partial(next, iterator)) + if callbacks is None: + callbacks = [] + elif callable(callbacks): + callbacks = [callbacks] + else: + callbacks = list(callbacks) + iterable_close = getattr(iterable, "close", None) + if iterable_close: + callbacks.insert(0, iterable_close) + self._callbacks = callbacks + + def __iter__(self) -> "ClosingIterator": + return self + + def __next__(self) -> bytes: + return self._next() + + def close(self) -> None: + for callback in self._callbacks: + callback() + + +def wrap_file( + environ: "WSGIEnvironment", file: t.IO[bytes], buffer_size: int = 8192 +) -> t.Iterable[bytes]: + """Wraps a file. This uses the WSGI server's file wrapper if available + or otherwise the generic :class:`FileWrapper`. + + .. versionadded:: 0.5 + + If the file wrapper from the WSGI server is used it's important to not + iterate over it from inside the application but to pass it through + unchanged. If you want to pass out a file wrapper inside a response + object you have to set :attr:`Response.direct_passthrough` to `True`. + + More information about file wrappers are available in :pep:`333`. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + return environ.get("wsgi.file_wrapper", FileWrapper)( # type: ignore + file, buffer_size + ) + + +class FileWrapper: + """This class can be used to convert a :class:`file`-like object into + an iterable. It yields `buffer_size` blocks until the file is fully + read. + + You should not use this class directly but rather use the + :func:`wrap_file` function that uses the WSGI server's file wrapper + support if it's available. + + .. versionadded:: 0.5 + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + + def __init__(self, file: t.IO[bytes], buffer_size: int = 8192) -> None: + self.file = file + self.buffer_size = buffer_size + + def close(self) -> None: + if hasattr(self.file, "close"): + self.file.close() + + def seekable(self) -> bool: + if hasattr(self.file, "seekable"): + return self.file.seekable() + if hasattr(self.file, "seek"): + return True + return False + + def seek(self, *args: t.Any) -> None: + if hasattr(self.file, "seek"): + self.file.seek(*args) + + def tell(self) -> t.Optional[int]: + if hasattr(self.file, "tell"): + return self.file.tell() + return None + + def __iter__(self) -> "FileWrapper": + return self + + def __next__(self) -> bytes: + data = self.file.read(self.buffer_size) + if data: + return data + raise StopIteration() + + +class _RangeWrapper: + # private for now, but should we make it public in the future ? + + """This class can be used to convert an iterable object into + an iterable that will only yield a piece of the underlying content. + It yields blocks until the underlying stream range is fully read. + The yielded blocks will have a size that can't exceed the original + iterator defined block size, but that can be smaller. + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param iterable: an iterable object with a :meth:`__next__` method. + :param start_byte: byte from which read will start. + :param byte_range: how many bytes to read. + """ + + def __init__( + self, + iterable: t.Union[t.Iterable[bytes], t.IO[bytes]], + start_byte: int = 0, + byte_range: t.Optional[int] = None, + ): + self.iterable = iter(iterable) + self.byte_range = byte_range + self.start_byte = start_byte + self.end_byte = None + + if byte_range is not None: + self.end_byte = start_byte + byte_range + + self.read_length = 0 + self.seekable = ( + hasattr(iterable, "seekable") and iterable.seekable() # type: ignore + ) + self.end_reached = False + + def __iter__(self) -> "_RangeWrapper": + return self + + def _next_chunk(self) -> bytes: + try: + chunk = next(self.iterable) + self.read_length += len(chunk) + return chunk + except StopIteration: + self.end_reached = True + raise + + def _first_iteration(self) -> t.Tuple[t.Optional[bytes], int]: + chunk = None + if self.seekable: + self.iterable.seek(self.start_byte) # type: ignore + self.read_length = self.iterable.tell() # type: ignore + contextual_read_length = self.read_length + else: + while self.read_length <= self.start_byte: + chunk = self._next_chunk() + if chunk is not None: + chunk = chunk[self.start_byte - self.read_length :] + contextual_read_length = self.start_byte + return chunk, contextual_read_length + + def _next(self) -> bytes: + if self.end_reached: + raise StopIteration() + chunk = None + contextual_read_length = self.read_length + if self.read_length == 0: + chunk, contextual_read_length = self._first_iteration() + if chunk is None: + chunk = self._next_chunk() + if self.end_byte is not None and self.read_length >= self.end_byte: + self.end_reached = True + return chunk[: self.end_byte - contextual_read_length] + return chunk + + def __next__(self) -> bytes: + chunk = self._next() + if chunk: + return chunk + self.end_reached = True + raise StopIteration() + + def close(self) -> None: + if hasattr(self.iterable, "close"): + self.iterable.close() # type: ignore + + +def _make_chunk_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + limit: t.Optional[int], + buffer_size: int, +) -> t.Iterator[bytes]: + """Helper for the line and chunk iter functions.""" + if isinstance(stream, (bytes, bytearray, str)): + raise TypeError( + "Passed a string or byte object instead of true iterator or stream." + ) + if not hasattr(stream, "read"): + for item in stream: + if item: + yield item + return + stream = t.cast(t.IO[bytes], stream) + if not isinstance(stream, LimitedStream) and limit is not None: + stream = t.cast(t.IO[bytes], LimitedStream(stream, limit)) + _read = stream.read + while True: + item = _read(buffer_size) + if not item: + break + yield item + + +def make_line_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + limit: t.Optional[int] = None, + buffer_size: int = 10 * 1024, + cap_at_buffer: bool = False, +) -> t.Iterator[bytes]: + """Safely iterates line-based over an input stream. If the input stream + is not a :class:`LimitedStream` the `limit` parameter is mandatory. + + This uses the stream's :meth:`~file.read` method internally as opposite + to the :meth:`~file.readline` method that is unsafe and can only be used + in violation of the WSGI specification. The same problem applies to the + `__iter__` function of the input stream which calls :meth:`~file.readline` + without arguments. + + If you need line-by-line processing it's strongly recommended to iterate + over the input stream using this helper function. + + .. versionchanged:: 0.8 + This function now ensures that the limit was reached. + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is a :class:`LimitedStream`. + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, "") + if not first_item: + return + + s = _make_encode_wrapper(first_item) + empty = t.cast(bytes, s("")) + cr = t.cast(bytes, s("\r")) + lf = t.cast(bytes, s("\n")) + crlf = t.cast(bytes, s("\r\n")) + + _iter = t.cast(t.Iterator[bytes], chain((first_item,), _iter)) + + def _iter_basic_lines() -> t.Iterator[bytes]: + _join = empty.join + buffer: t.List[bytes] = [] + while True: + new_data = next(_iter, "") + if not new_data: + break + new_buf: t.List[bytes] = [] + buf_size = 0 + for item in t.cast( + t.Iterator[bytes], chain(buffer, new_data.splitlines(True)) + ): + new_buf.append(item) + buf_size += len(item) + if item and item[-1:] in crlf: + yield _join(new_buf) + new_buf = [] + elif cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buffer = new_buf + if buffer: + yield _join(buffer) + + # This hackery is necessary to merge 'foo\r' and '\n' into one item + # of 'foo\r\n' if we were unlucky and we hit a chunk boundary. + previous = empty + for item in _iter_basic_lines(): + if item == lf and previous[-1:] == cr: + previous += item + item = empty + if previous: + yield previous + previous = item + if previous: + yield previous + + +def make_chunk_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + separator: bytes, + limit: t.Optional[int] = None, + buffer_size: int = 10 * 1024, + cap_at_buffer: bool = False, +) -> t.Iterator[bytes]: + """Works like :func:`make_line_iter` but accepts a separator + which divides chunks. If you want newline based processing + you should use :func:`make_line_iter` instead as it + supports arbitrary newline markers. + + .. versionadded:: 0.8 + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param separator: the separator that divides chunks. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is otherwise already limited). + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, b"") + if not first_item: + return + + _iter = t.cast(t.Iterator[bytes], chain((first_item,), _iter)) + if isinstance(first_item, str): + separator = _to_str(separator) + _split = re.compile(f"({re.escape(separator)})").split + _join = "".join + else: + separator = _to_bytes(separator) + _split = re.compile(b"(" + re.escape(separator) + b")").split + _join = b"".join + + buffer: t.List[bytes] = [] + while True: + new_data = next(_iter, b"") + if not new_data: + break + chunks = _split(new_data) + new_buf: t.List[bytes] = [] + buf_size = 0 + for item in chain(buffer, chunks): + if item == separator: + yield _join(new_buf) + new_buf = [] + buf_size = 0 + else: + buf_size += len(item) + new_buf.append(item) + + if cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buf_size = len(rv) + + buffer = new_buf + if buffer: + yield _join(buffer) + + +class LimitedStream(io.IOBase): + """Wraps a stream so that it doesn't read more than n bytes. If the + stream is exhausted and the caller tries to get more bytes from it + :func:`on_exhausted` is called which by default returns an empty + string. The return value of that function is forwarded + to the reader function. So if it returns an empty string + :meth:`read` will return an empty string as well. + + The limit however must never be higher than what the stream can + output. Otherwise :meth:`readlines` will try to read past the + limit. + + .. admonition:: Note on WSGI compliance + + calls to :meth:`readline` and :meth:`readlines` are not + WSGI compliant because it passes a size argument to the + readline methods. Unfortunately the WSGI PEP is not safely + implementable without a size argument to :meth:`readline` + because there is no EOF marker in the stream. As a result + of that the use of :meth:`readline` is discouraged. + + For the same reason iterating over the :class:`LimitedStream` + is not portable. It internally calls :meth:`readline`. + + We strongly suggest using :meth:`read` only or using the + :func:`make_line_iter` which safely iterates line-based + over a WSGI input stream. + + :param stream: the stream to wrap. + :param limit: the limit for the stream, must not be longer than + what the string can provide if the stream does not + end with `EOF` (like `wsgi.input`) + """ + + def __init__(self, stream: t.IO[bytes], limit: int) -> None: + self._read = stream.read + self._readline = stream.readline + self._pos = 0 + self.limit = limit + + def __iter__(self) -> "LimitedStream": + return self + + @property + def is_exhausted(self) -> bool: + """If the stream is exhausted this attribute is `True`.""" + return self._pos >= self.limit + + def on_exhausted(self) -> bytes: + """This is called when the stream tries to read past the limit. + The return value of this function is returned from the reading + function. + """ + # Read null bytes from the stream so that we get the + # correct end of stream marker. + return self._read(0) + + def on_disconnect(self) -> bytes: + """What should happen if a disconnect is detected? The return + value of this function is returned from read functions in case + the client went away. By default a + :exc:`~werkzeug.exceptions.ClientDisconnected` exception is raised. + """ + from .exceptions import ClientDisconnected + + raise ClientDisconnected() + + def exhaust(self, chunk_size: int = 1024 * 64) -> None: + """Exhaust the stream. This consumes all the data left until the + limit is reached. + + :param chunk_size: the size for a chunk. It will read the chunk + until the stream is exhausted and throw away + the results. + """ + to_read = self.limit - self._pos + chunk = chunk_size + while to_read > 0: + chunk = min(to_read, chunk) + self.read(chunk) + to_read -= chunk + + def read(self, size: t.Optional[int] = None) -> bytes: + """Read `size` bytes or if size is not provided everything is read. + + :param size: the number of bytes read. + """ + if self._pos >= self.limit: + return self.on_exhausted() + if size is None or size == -1: # -1 is for consistence with file + size = self.limit + to_read = min(self.limit - self._pos, size) + try: + read = self._read(to_read) + except (OSError, ValueError): + return self.on_disconnect() + if to_read and len(read) != to_read: + return self.on_disconnect() + self._pos += len(read) + return read + + def readline(self, size: t.Optional[int] = None) -> bytes: + """Reads one line from the stream.""" + if self._pos >= self.limit: + return self.on_exhausted() + if size is None: + size = self.limit - self._pos + else: + size = min(size, self.limit - self._pos) + try: + line = self._readline(size) + except (ValueError, OSError): + return self.on_disconnect() + if size and not line: + return self.on_disconnect() + self._pos += len(line) + return line + + def readlines(self, size: t.Optional[int] = None) -> t.List[bytes]: + """Reads a file into a list of strings. It calls :meth:`readline` + until the file is read to the end. It does support the optional + `size` argument if the underlying stream supports it for + `readline`. + """ + last_pos = self._pos + result = [] + if size is not None: + end = min(self.limit, last_pos + size) + else: + end = self.limit + while True: + if size is not None: + size -= last_pos - self._pos + if self._pos >= end: + break + result.append(self.readline(size)) + if size is not None: + last_pos = self._pos + return result + + def tell(self) -> int: + """Returns the position of the stream. + + .. versionadded:: 0.9 + """ + return self._pos + + def __next__(self) -> bytes: + line = self.readline() + if not line: + raise StopIteration() + return line + + def readable(self) -> bool: + return True diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/LICENSE new file mode 100644 index 0000000..cc10784 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Benno Rice and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/METADATA new file mode 100644 index 0000000..32e8bdb --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/METADATA @@ -0,0 +1,177 @@ +Metadata-Version: 2.1 +Name: wsproto +Version: 1.2.0 +Summary: WebSockets state-machine based protocol implementation +Home-page: https://github.com/python-hyper/wsproto/ +Author: Benno Rice +Author-email: benno@jeamland.net +License: MIT License +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.7.0 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: h11 (<1,>=0.9.0) + +======================================================== +Pure Python, pure state-machine WebSocket implementation +======================================================== + +.. image:: https://github.com/python-hyper/wsproto/workflows/CI/badge.svg + :target: https://github.com/python-hyper/wsproto/actions + :alt: Build Status +.. image:: https://codecov.io/gh/python-hyper/wsproto/branch/main/graph/badge.svg + :target: https://codecov.io/gh/python-hyper/wsproto + :alt: Code Coverage +.. image:: https://readthedocs.org/projects/wsproto/badge/?version=latest + :target: https://wsproto.readthedocs.io/en/latest/ + :alt: Documentation Status +.. image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg + :target: https://gitter.im/python-hyper/community + :alt: Chat community + + +This repository contains a pure-Python implementation of a WebSocket protocol +stack. It's written from the ground up to be embeddable in whatever program you +choose to use, ensuring that you can communicate via WebSockets, as defined in +`RFC6455 `_, regardless of your programming +paradigm. + +This repository does not provide a parsing layer, a network layer, or any rules +about concurrency. Instead, it's a purely in-memory solution, defined in terms +of data actions and WebSocket frames. RFC6455 and Compression Extensions for +WebSocket via `RFC7692 `_ are fully +supported. + +wsproto supports Python 3.6.1 or higher. + +To install it, just run: + +.. code-block:: console + + $ pip install wsproto + + +Usage +===== + +Let's assume you have some form of network socket available. wsproto client +connections automatically generate a HTTP request to initiate the WebSocket +handshake. To create a WebSocket client connection: + +.. code-block:: python + + from wsproto import WSConnection, ConnectionType + from wsproto.events import Request + + ws = WSConnection(ConnectionType.CLIENT) + ws.send(Request(host='echo.websocket.org', target='/')) + +To create a WebSocket server connection: + +.. code-block:: python + + from wsproto.connection import WSConnection, ConnectionType + + ws = WSConnection(ConnectionType.SERVER) + +Every time you send a message, or call a ping, or simply if you receive incoming +data, wsproto might respond with some outgoing data that you have to send: + +.. code-block:: python + + some_socket.send(ws.bytes_to_send()) + +Both connection types need to receive incoming data: + +.. code-block:: python + + ws.receive_data(some_byte_string_of_data) + +And wsproto will issue events if the data contains any WebSocket messages or state changes: + +.. code-block:: python + + for event in ws.events(): + if isinstance(event, Request): + # only client connections get this event + ws.send(AcceptConnection()) + elif isinstance(event, CloseConnection): + # guess nobody wants to talk to us any more... + elif isinstance(event, TextMessage): + print('We got text!', event.data) + elif isinstance(event, BytesMessage): + print('We got bytes!', event.data) + +Take a look at our docs for a `full list of events +`! + +Testing +======= + +It passes the autobahn test suite completely and strictly in both client and +server modes and using permessage-deflate. + +If you want to run the compliance tests, go into the compliance directory and +then to test client mode, in one shell run the Autobahn test server: + +.. code-block:: console + + $ wstest -m fuzzingserver -s ws-fuzzingserver.json + +And in another shell run the test client: + +.. code-block:: console + + $ python test_client.py + +And to test server mode, run the test server: + +.. code-block:: console + + $ python test_server.py + +And in another shell run the Autobahn test client: + +.. code-block:: console + + $ wstest -m fuzzingclient -s ws-fuzzingclient.json + + +Documentation +============= + +Documentation is available at https://wsproto.readthedocs.io/en/latest/. + +Contributing +============ + +``wsproto`` welcomes contributions from anyone! Unlike many other projects we +are happy to accept cosmetic contributions and small contributions, in addition +to large feature requests and changes. + +Before you contribute (either by opening an issue or filing a pull request), +please `read the contribution guidelines`_. + +.. _read the contribution guidelines: http://python-hyper.org/en/latest/contributing.html + +License +======= + +``wsproto`` is made available under the MIT License. For more details, see the +``LICENSE`` file in the repository. + +Authors +======= + +``wsproto`` was created by @jeamland, and is maintained by the python-hyper +community. diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/RECORD new file mode 100644 index 0000000..be33ce4 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/RECORD @@ -0,0 +1,23 @@ +wsproto-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +wsproto-1.2.0.dist-info/LICENSE,sha256=wDKajb80N7CV9_XPQlfWu4VeBxIMroeGWGBz_3ppmVk,1093 +wsproto-1.2.0.dist-info/METADATA,sha256=V7EI9a-gXS3NLxeYYmWqtf_MkMfepGoTF03IaR-OVwo,5607 +wsproto-1.2.0.dist-info/RECORD,, +wsproto-1.2.0.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92 +wsproto-1.2.0.dist-info/top_level.txt,sha256=BUdIrwL11zET0fkWkYRJ1yZKrEfvDF9DZqjhABOio6Y,8 +wsproto/__init__.py,sha256=zQSIjLjveTHwyhGAfqG_n_cVl54hTkeV6vuad1cnEOE,2887 +wsproto/__pycache__/__init__.cpython-310.pyc,, +wsproto/__pycache__/connection.cpython-310.pyc,, +wsproto/__pycache__/events.cpython-310.pyc,, +wsproto/__pycache__/extensions.cpython-310.pyc,, +wsproto/__pycache__/frame_protocol.cpython-310.pyc,, +wsproto/__pycache__/handshake.cpython-310.pyc,, +wsproto/__pycache__/typing.cpython-310.pyc,, +wsproto/__pycache__/utilities.cpython-310.pyc,, +wsproto/connection.py,sha256=LhsbokxZUmAtMsOFFZ45puZDPyIXNEmq7SanE7swAgE,6813 +wsproto/events.py,sha256=DW7YQ823oK3MjXHqcPvjJzjBGk5UGuMO_rpNnKgmmW8,7979 +wsproto/extensions.py,sha256=VlnojvsC2AO7vbUkw_TOqCgtmHb1dSplXeRwjMfjCo4,11211 +wsproto/frame_protocol.py,sha256=B5p_wRq54gvTihegbJ39RkONrdhtipoYDEiYq95BdAk,23401 +wsproto/handshake.py,sha256=hPqTo15MqOxYlvcNYTo-bIzQJHtRLq8qq2jBdHdz2x8,18036 +wsproto/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 +wsproto/typing.py,sha256=Ryf6eOhAzfZlHCFELiiayDzNqdXQG7JKccblOqNx6Wo,68 +wsproto/utilities.py,sha256=5qmPXSUhUp2GESgvgIacZ7N4uqd0vBijhVV7t6XTiZw,2816 diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/WHEEL new file mode 100644 index 0000000..5bad85f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/top_level.txt new file mode 100644 index 0000000..8b7d144 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto-1.2.0.dist-info/top_level.txt @@ -0,0 +1 @@ +wsproto diff --git a/axios-example/lib/python3.10/site-packages/wsproto/__init__.py b/axios-example/lib/python3.10/site-packages/wsproto/__init__.py new file mode 100644 index 0000000..46fde3f --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/__init__.py @@ -0,0 +1,94 @@ +""" +wsproto +~~~~~~~ + +A WebSocket implementation. +""" +from typing import Generator, Optional, Union + +from .connection import Connection, ConnectionState, ConnectionType +from .events import Event +from .handshake import H11Handshake +from .typing import Headers + +__version__ = "1.2.0" + + +class WSConnection: + """ + Represents the local end of a WebSocket connection to a remote peer. + """ + + def __init__(self, connection_type: ConnectionType) -> None: + """ + Constructor + + :param wsproto.connection.ConnectionType connection_type: Controls + whether the library behaves as a client or as a server. + """ + self.client = connection_type is ConnectionType.CLIENT + self.handshake = H11Handshake(connection_type) + self.connection: Optional[Connection] = None + + @property + def state(self) -> ConnectionState: + """ + :returns: Connection state + :rtype: wsproto.connection.ConnectionState + """ + if self.connection is None: + return self.handshake.state + return self.connection.state + + def initiate_upgrade_connection( + self, headers: Headers, path: Union[bytes, str] + ) -> None: + self.handshake.initiate_upgrade_connection(headers, path) + + def send(self, event: Event) -> bytes: + """ + Generate network data for the specified event. + + When you want to communicate with a WebSocket peer, you should construct + an event and pass it to this method. This method will return the bytes + that you should send to the peer. + + :param wsproto.events.Event event: The event to generate data for + :returns bytes: The data to send to the peer + """ + data = b"" + if self.connection is None: + data += self.handshake.send(event) + self.connection = self.handshake.connection + else: + data += self.connection.send(event) + return data + + def receive_data(self, data: Optional[bytes]) -> None: + """ + Feed network data into the connection instance. + + After calling this method, you should call :meth:`events` to see if the + received data triggered any new events. + + :param bytes data: Data received from remote peer + """ + if self.connection is None: + self.handshake.receive_data(data) + self.connection = self.handshake.connection + else: + self.connection.receive_data(data) + + def events(self) -> Generator[Event, None, None]: + """ + A generator that yields pending events. + + Each event is an instance of a subclass of + :class:`wsproto.events.Event`. + """ + yield from self.handshake.events() + if self.connection is not None: + yield from self.connection.events() + + +__all__ = ("ConnectionType", "WSConnection") diff --git a/axios-example/lib/python3.10/site-packages/wsproto/connection.py b/axios-example/lib/python3.10/site-packages/wsproto/connection.py new file mode 100644 index 0000000..4439165 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/connection.py @@ -0,0 +1,189 @@ +""" +wsproto/connection +~~~~~~~~~~~~~~~~~~ + +An implementation of a WebSocket connection. +""" + +from collections import deque +from enum import Enum +from typing import Deque, Generator, List, Optional + +from .events import ( + BytesMessage, + CloseConnection, + Event, + Message, + Ping, + Pong, + TextMessage, +) +from .extensions import Extension +from .frame_protocol import CloseReason, FrameProtocol, Opcode, ParseFailed +from .utilities import LocalProtocolError + + +class ConnectionState(Enum): + """ + RFC 6455, Section 4 - Opening Handshake + """ + + #: The opening handshake is in progress. + CONNECTING = 0 + #: The opening handshake is complete. + OPEN = 1 + #: The remote WebSocket has initiated a connection close. + REMOTE_CLOSING = 2 + #: The local WebSocket (i.e. this instance) has initiated a connection close. + LOCAL_CLOSING = 3 + #: The closing handshake has completed. + CLOSED = 4 + #: The connection was rejected during the opening handshake. + REJECTING = 5 + + +class ConnectionType(Enum): + """An enumeration of connection types.""" + + #: This connection will act as client and talk to a remote server + CLIENT = 1 + + #: This connection will as as server and waits for client connections + SERVER = 2 + + +CLIENT = ConnectionType.CLIENT +SERVER = ConnectionType.SERVER + + +class Connection: + """ + A low-level WebSocket connection object. + + This wraps two other protocol objects, an HTTP/1.1 protocol object used + to do the initial HTTP upgrade handshake and a WebSocket frame protocol + object used to exchange messages and other control frames. + + :param conn_type: Whether this object is on the client- or server-side of + a connection. To initialise as a client pass ``CLIENT`` otherwise + pass ``SERVER``. + :type conn_type: ``ConnectionType`` + """ + + def __init__( + self, + connection_type: ConnectionType, + extensions: Optional[List[Extension]] = None, + trailing_data: bytes = b"", + ) -> None: + self.client = connection_type is ConnectionType.CLIENT + self._events: Deque[Event] = deque() + self._proto = FrameProtocol(self.client, extensions or []) + self._state = ConnectionState.OPEN + self.receive_data(trailing_data) + + @property + def state(self) -> ConnectionState: + return self._state + + def send(self, event: Event) -> bytes: + data = b"" + if isinstance(event, Message) and self.state == ConnectionState.OPEN: + data += self._proto.send_data(event.data, event.message_finished) + elif isinstance(event, Ping) and self.state == ConnectionState.OPEN: + data += self._proto.ping(event.payload) + elif isinstance(event, Pong) and self.state == ConnectionState.OPEN: + data += self._proto.pong(event.payload) + elif isinstance(event, CloseConnection) and self.state in { + ConnectionState.OPEN, + ConnectionState.REMOTE_CLOSING, + }: + data += self._proto.close(event.code, event.reason) + if self.state == ConnectionState.REMOTE_CLOSING: + self._state = ConnectionState.CLOSED + else: + self._state = ConnectionState.LOCAL_CLOSING + else: + raise LocalProtocolError( + f"Event {event} cannot be sent in state {self.state}." + ) + return data + + def receive_data(self, data: Optional[bytes]) -> None: + """ + Pass some received data to the connection for handling. + + A list of events that the remote peer triggered by sending this data can + be retrieved with :meth:`~wsproto.connection.Connection.events`. + + :param data: The data received from the remote peer on the network. + :type data: ``bytes`` + """ + + if data is None: + # "If _The WebSocket Connection is Closed_ and no Close control + # frame was received by the endpoint (such as could occur if the + # underlying transport connection is lost), _The WebSocket + # Connection Close Code_ is considered to be 1006." + self._events.append(CloseConnection(code=CloseReason.ABNORMAL_CLOSURE)) + self._state = ConnectionState.CLOSED + return + + if self.state in (ConnectionState.OPEN, ConnectionState.LOCAL_CLOSING): + self._proto.receive_bytes(data) + elif self.state is ConnectionState.CLOSED: + raise LocalProtocolError("Connection already closed.") + else: + pass # pragma: no cover + + def events(self) -> Generator[Event, None, None]: + """ + Return a generator that provides any events that have been generated + by protocol activity. + + :returns: generator of :class:`Event ` subclasses + """ + while self._events: + yield self._events.popleft() + + try: + for frame in self._proto.received_frames(): + if frame.opcode is Opcode.PING: + assert frame.frame_finished and frame.message_finished + assert isinstance(frame.payload, (bytes, bytearray)) + yield Ping(payload=frame.payload) + + elif frame.opcode is Opcode.PONG: + assert frame.frame_finished and frame.message_finished + assert isinstance(frame.payload, (bytes, bytearray)) + yield Pong(payload=frame.payload) + + elif frame.opcode is Opcode.CLOSE: + assert isinstance(frame.payload, tuple) + code, reason = frame.payload + if self.state is ConnectionState.LOCAL_CLOSING: + self._state = ConnectionState.CLOSED + else: + self._state = ConnectionState.REMOTE_CLOSING + yield CloseConnection(code=code, reason=reason) + + elif frame.opcode is Opcode.TEXT: + assert isinstance(frame.payload, str) + yield TextMessage( + data=frame.payload, + frame_finished=frame.frame_finished, + message_finished=frame.message_finished, + ) + + elif frame.opcode is Opcode.BINARY: + assert isinstance(frame.payload, (bytes, bytearray)) + yield BytesMessage( + data=frame.payload, + frame_finished=frame.frame_finished, + message_finished=frame.message_finished, + ) + + else: + pass # pragma: no cover + except ParseFailed as exc: + yield CloseConnection(code=exc.code, reason=str(exc)) diff --git a/axios-example/lib/python3.10/site-packages/wsproto/events.py b/axios-example/lib/python3.10/site-packages/wsproto/events.py new file mode 100644 index 0000000..d758f8a --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/events.py @@ -0,0 +1,295 @@ +""" +wsproto/events +~~~~~~~~~~~~~~ + +Events that result from processing data on a WebSocket connection. +""" +from abc import ABC +from dataclasses import dataclass, field +from typing import Generic, List, Optional, Sequence, TypeVar, Union + +from .extensions import Extension +from .typing import Headers + + +class Event(ABC): + """ + Base class for wsproto events. + """ + + pass # noqa + + +@dataclass(frozen=True) +class Request(Event): + """The beginning of a Websocket connection, the HTTP Upgrade request + + This event is fired when a SERVER connection receives a WebSocket + handshake request (HTTP with upgrade header). + + Fields: + + .. attribute:: host + + (Required) The hostname, or host header value. + + .. attribute:: target + + (Required) The request target (path and query string) + + .. attribute:: extensions + + The proposed extensions. + + .. attribute:: extra_headers + + The additional request headers, excluding extensions, host, subprotocols, + and version headers. + + .. attribute:: subprotocols + + A list of the subprotocols proposed in the request, as a list + of strings. + """ + + host: str + target: str + extensions: Union[Sequence[Extension], Sequence[str]] = field( # type: ignore[assignment] + default_factory=list + ) + extra_headers: Headers = field(default_factory=list) + subprotocols: List[str] = field(default_factory=list) + + +@dataclass(frozen=True) +class AcceptConnection(Event): + """The acceptance of a Websocket upgrade request. + + This event is fired when a CLIENT receives an acceptance response + from a server. It is also used to accept an upgrade request when + acting as a SERVER. + + Fields: + + .. attribute:: extra_headers + + Any additional (non websocket related) headers present in the + acceptance response. + + .. attribute:: subprotocol + + The accepted subprotocol to use. + + """ + + subprotocol: Optional[str] = None + extensions: List[Extension] = field(default_factory=list) + extra_headers: Headers = field(default_factory=list) + + +@dataclass(frozen=True) +class RejectConnection(Event): + """The rejection of a Websocket upgrade request, the HTTP response. + + The ``RejectConnection`` event sends the appropriate HTTP headers to + communicate to the peer that the handshake has been rejected. You may also + send an HTTP body by setting the ``has_body`` attribute to ``True`` and then + sending one or more :class:`RejectData` events after this one. When sending + a response body, the caller should set the ``Content-Length``, + ``Content-Type``, and/or ``Transfer-Encoding`` headers as appropriate. + + When receiving a ``RejectConnection`` event, the ``has_body`` attribute will + in almost all cases be ``True`` (even if the server set it to ``False``) and + will be followed by at least one ``RejectData`` events, even though the data + itself might be just ``b""``. (The only scenario in which the caller + receives a ``RejectConnection`` with ``has_body == False`` is if the peer + violates sends an informational status code (1xx) other than 101.) + + The ``has_body`` attribute should only be used when receiving the event. (It + has ) is False the headers must include a + content-length or transfer encoding. + + Fields: + + .. attribute:: headers (Headers) + + The headers to send with the response. + + .. attribute:: has_body + + This defaults to False, but set to True if there is a body. See + also :class:`~RejectData`. + + .. attribute:: status_code + + The response status code. + + """ + + status_code: int = 400 + headers: Headers = field(default_factory=list) + has_body: bool = False + + +@dataclass(frozen=True) +class RejectData(Event): + """The rejection HTTP response body. + + The caller may send multiple ``RejectData`` events. The final event should + have the ``body_finished`` attribute set to ``True``. + + Fields: + + .. attribute:: body_finished + + True if this is the final chunk of the body data. + + .. attribute:: data (bytes) + + (Required) The raw body data. + + """ + + data: bytes + body_finished: bool = True + + +@dataclass(frozen=True) +class CloseConnection(Event): + + """The end of a Websocket connection, represents a closure frame. + + **wsproto does not automatically send a response to a close event.** To + comply with the RFC you MUST send a close event back to the remote WebSocket + if you have not already sent one. The :meth:`response` method provides a + suitable event for this purpose, and you should check if a response needs + to be sent by checking :func:`wsproto.WSConnection.state`. + + Fields: + + .. attribute:: code + + (Required) The integer close code to indicate why the connection + has closed. + + .. attribute:: reason + + Additional reasoning for why the connection has closed. + + """ + + code: int + reason: Optional[str] = None + + def response(self) -> "CloseConnection": + """Generate an RFC-compliant close frame to send back to the peer.""" + return CloseConnection(code=self.code, reason=self.reason) + + +T = TypeVar("T", bytes, str) + + +@dataclass(frozen=True) +class Message(Event, Generic[T]): + """The websocket data message. + + Fields: + + .. attribute:: data + + (Required) The message data as byte string, can be decoded as UTF-8 for + TEXT messages. This only represents a single chunk of data and + not a full WebSocket message. You need to buffer and + reassemble these chunks to get the full message. + + .. attribute:: frame_finished + + This has no semantic content, but is provided just in case some + weird edge case user wants to be able to reconstruct the + fragmentation pattern of the original stream. + + .. attribute:: message_finished + + True if this frame is the last one of this message, False if + more frames are expected. + + """ + + data: T + frame_finished: bool = True + message_finished: bool = True + + +@dataclass(frozen=True) +class TextMessage(Message[str]): # pylint: disable=unsubscriptable-object + """This event is fired when a data frame with TEXT payload is received. + + Fields: + + .. attribute:: data + + The message data as string, This only represents a single chunk + of data and not a full WebSocket message. You need to buffer + and reassemble these chunks to get the full message. + + """ + + # https://github.com/python/mypy/issues/5744 + data: str + + +@dataclass(frozen=True) +class BytesMessage(Message[bytes]): # pylint: disable=unsubscriptable-object + """This event is fired when a data frame with BINARY payload is + received. + + Fields: + + .. attribute:: data + + The message data as byte string, can be decoded as UTF-8 for + TEXT messages. This only represents a single chunk of data and + not a full WebSocket message. You need to buffer and + reassemble these chunks to get the full message. + """ + + # https://github.com/python/mypy/issues/5744 + data: bytes + + +@dataclass(frozen=True) +class Ping(Event): + """The Ping event can be sent to trigger a ping frame and is fired + when a Ping is received. + + **wsproto does not automatically send a pong response to a ping event.** To + comply with the RFC you MUST send a pong even as soon as is practical. The + :meth:`response` method provides a suitable event for this purpose. + + Fields: + + .. attribute:: payload + + An optional payload to emit with the ping frame. + """ + + payload: bytes = b"" + + def response(self) -> "Pong": + """Generate an RFC-compliant :class:`Pong` response to this ping.""" + return Pong(payload=self.payload) + + +@dataclass(frozen=True) +class Pong(Event): + """The Pong event is fired when a Pong is received. + + Fields: + + .. attribute:: payload + + An optional payload to emit with the pong frame. + + """ + + payload: bytes = b"" diff --git a/axios-example/lib/python3.10/site-packages/wsproto/extensions.py b/axios-example/lib/python3.10/site-packages/wsproto/extensions.py new file mode 100644 index 0000000..ea8555d --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/extensions.py @@ -0,0 +1,315 @@ +""" +wsproto/extensions +~~~~~~~~~~~~~~~~~~ + +WebSocket extensions. +""" + +import zlib +from typing import Optional, Tuple, Union + +from .frame_protocol import CloseReason, FrameDecoder, FrameProtocol, Opcode, RsvBits + + +class Extension: + name: str + + def enabled(self) -> bool: + return False + + def offer(self) -> Union[bool, str]: + pass + + def accept(self, offer: str) -> Optional[Union[bool, str]]: + pass + + def finalize(self, offer: str) -> None: + pass + + def frame_inbound_header( + self, + proto: Union[FrameDecoder, FrameProtocol], + opcode: Opcode, + rsv: RsvBits, + payload_length: int, + ) -> Union[CloseReason, RsvBits]: + return RsvBits(False, False, False) + + def frame_inbound_payload_data( + self, proto: Union[FrameDecoder, FrameProtocol], data: bytes + ) -> Union[bytes, CloseReason]: + return data + + def frame_inbound_complete( + self, proto: Union[FrameDecoder, FrameProtocol], fin: bool + ) -> Union[bytes, CloseReason, None]: + pass + + def frame_outbound( + self, + proto: Union[FrameDecoder, FrameProtocol], + opcode: Opcode, + rsv: RsvBits, + data: bytes, + fin: bool, + ) -> Tuple[RsvBits, bytes]: + return (rsv, data) + + +class PerMessageDeflate(Extension): + name = "permessage-deflate" + + DEFAULT_CLIENT_MAX_WINDOW_BITS = 15 + DEFAULT_SERVER_MAX_WINDOW_BITS = 15 + + def __init__( + self, + client_no_context_takeover: bool = False, + client_max_window_bits: Optional[int] = None, + server_no_context_takeover: bool = False, + server_max_window_bits: Optional[int] = None, + ) -> None: + self.client_no_context_takeover = client_no_context_takeover + self.server_no_context_takeover = server_no_context_takeover + self._client_max_window_bits = self.DEFAULT_CLIENT_MAX_WINDOW_BITS + self._server_max_window_bits = self.DEFAULT_SERVER_MAX_WINDOW_BITS + if client_max_window_bits is not None: + self.client_max_window_bits = client_max_window_bits + if server_max_window_bits is not None: + self.server_max_window_bits = server_max_window_bits + + self._compressor: Optional[zlib._Compress] = None # noqa + self._decompressor: Optional[zlib._Decompress] = None # noqa + # This refers to the current frame + self._inbound_is_compressible: Optional[bool] = None + # This refers to the ongoing message (which might span multiple + # frames). Only the first frame in a fragmented message is flagged for + # compression, so this carries that bit forward. + self._inbound_compressed: Optional[bool] = None + + self._enabled = False + + @property + def client_max_window_bits(self) -> int: + return self._client_max_window_bits + + @client_max_window_bits.setter + def client_max_window_bits(self, value: int) -> None: + if value < 9 or value > 15: + raise ValueError("Window size must be between 9 and 15 inclusive") + self._client_max_window_bits = value + + @property + def server_max_window_bits(self) -> int: + return self._server_max_window_bits + + @server_max_window_bits.setter + def server_max_window_bits(self, value: int) -> None: + if value < 9 or value > 15: + raise ValueError("Window size must be between 9 and 15 inclusive") + self._server_max_window_bits = value + + def _compressible_opcode(self, opcode: Opcode) -> bool: + return opcode in (Opcode.TEXT, Opcode.BINARY, Opcode.CONTINUATION) + + def enabled(self) -> bool: + return self._enabled + + def offer(self) -> Union[bool, str]: + parameters = [ + "client_max_window_bits=%d" % self.client_max_window_bits, + "server_max_window_bits=%d" % self.server_max_window_bits, + ] + + if self.client_no_context_takeover: + parameters.append("client_no_context_takeover") + if self.server_no_context_takeover: + parameters.append("server_no_context_takeover") + + return "; ".join(parameters) + + def finalize(self, offer: str) -> None: + bits = [b.strip() for b in offer.split(";")] + for bit in bits[1:]: + if bit.startswith("client_no_context_takeover"): + self.client_no_context_takeover = True + elif bit.startswith("server_no_context_takeover"): + self.server_no_context_takeover = True + elif bit.startswith("client_max_window_bits"): + self.client_max_window_bits = int(bit.split("=", 1)[1].strip()) + elif bit.startswith("server_max_window_bits"): + self.server_max_window_bits = int(bit.split("=", 1)[1].strip()) + + self._enabled = True + + def _parse_params(self, params: str) -> Tuple[Optional[int], Optional[int]]: + client_max_window_bits = None + server_max_window_bits = None + + bits = [b.strip() for b in params.split(";")] + for bit in bits[1:]: + if bit.startswith("client_no_context_takeover"): + self.client_no_context_takeover = True + elif bit.startswith("server_no_context_takeover"): + self.server_no_context_takeover = True + elif bit.startswith("client_max_window_bits"): + if "=" in bit: + client_max_window_bits = int(bit.split("=", 1)[1].strip()) + else: + client_max_window_bits = self.client_max_window_bits + elif bit.startswith("server_max_window_bits"): + if "=" in bit: + server_max_window_bits = int(bit.split("=", 1)[1].strip()) + else: + server_max_window_bits = self.server_max_window_bits + + return client_max_window_bits, server_max_window_bits + + def accept(self, offer: str) -> Union[bool, None, str]: + client_max_window_bits, server_max_window_bits = self._parse_params(offer) + + parameters = [] + + if self.client_no_context_takeover: + parameters.append("client_no_context_takeover") + if self.server_no_context_takeover: + parameters.append("server_no_context_takeover") + try: + if client_max_window_bits is not None: + parameters.append("client_max_window_bits=%d" % client_max_window_bits) + self.client_max_window_bits = client_max_window_bits + if server_max_window_bits is not None: + parameters.append("server_max_window_bits=%d" % server_max_window_bits) + self.server_max_window_bits = server_max_window_bits + except ValueError: + return None + else: + self._enabled = True + return "; ".join(parameters) + + def frame_inbound_header( + self, + proto: Union[FrameDecoder, FrameProtocol], + opcode: Opcode, + rsv: RsvBits, + payload_length: int, + ) -> Union[CloseReason, RsvBits]: + if rsv.rsv1 and opcode.iscontrol(): + return CloseReason.PROTOCOL_ERROR + if rsv.rsv1 and opcode is Opcode.CONTINUATION: + return CloseReason.PROTOCOL_ERROR + + self._inbound_is_compressible = self._compressible_opcode(opcode) + + if self._inbound_compressed is None: + self._inbound_compressed = rsv.rsv1 + if self._inbound_compressed: + assert self._inbound_is_compressible + if proto.client: + bits = self.server_max_window_bits + else: + bits = self.client_max_window_bits + if self._decompressor is None: + self._decompressor = zlib.decompressobj(-int(bits)) + + return RsvBits(True, False, False) + + def frame_inbound_payload_data( + self, proto: Union[FrameDecoder, FrameProtocol], data: bytes + ) -> Union[bytes, CloseReason]: + if not self._inbound_compressed or not self._inbound_is_compressible: + return data + assert self._decompressor is not None + + try: + return self._decompressor.decompress(bytes(data)) + except zlib.error: + return CloseReason.INVALID_FRAME_PAYLOAD_DATA + + def frame_inbound_complete( + self, proto: Union[FrameDecoder, FrameProtocol], fin: bool + ) -> Union[bytes, CloseReason, None]: + if not fin: + return None + if not self._inbound_is_compressible: + self._inbound_compressed = None + return None + if not self._inbound_compressed: + self._inbound_compressed = None + return None + assert self._decompressor is not None + + try: + data = self._decompressor.decompress(b"\x00\x00\xff\xff") + data += self._decompressor.flush() + except zlib.error: + return CloseReason.INVALID_FRAME_PAYLOAD_DATA + + if proto.client: + no_context_takeover = self.server_no_context_takeover + else: + no_context_takeover = self.client_no_context_takeover + + if no_context_takeover: + self._decompressor = None + + self._inbound_compressed = None + + return data + + def frame_outbound( + self, + proto: Union[FrameDecoder, FrameProtocol], + opcode: Opcode, + rsv: RsvBits, + data: bytes, + fin: bool, + ) -> Tuple[RsvBits, bytes]: + if not self._compressible_opcode(opcode): + return (rsv, data) + + if opcode is not Opcode.CONTINUATION: + rsv = RsvBits(True, *rsv[1:]) + + if self._compressor is None: + assert opcode is not Opcode.CONTINUATION + if proto.client: + bits = self.client_max_window_bits + else: + bits = self.server_max_window_bits + self._compressor = zlib.compressobj( + zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -int(bits) + ) + + data = self._compressor.compress(bytes(data)) + + if fin: + data += self._compressor.flush(zlib.Z_SYNC_FLUSH) + data = data[:-4] + + if proto.client: + no_context_takeover = self.client_no_context_takeover + else: + no_context_takeover = self.server_no_context_takeover + + if no_context_takeover: + self._compressor = None + + return (rsv, data) + + def __repr__(self) -> str: + descr = ["client_max_window_bits=%d" % self.client_max_window_bits] + if self.client_no_context_takeover: + descr.append("client_no_context_takeover") + descr.append("server_max_window_bits=%d" % self.server_max_window_bits) + if self.server_no_context_takeover: + descr.append("server_no_context_takeover") + + return "<{} {}>".format(self.__class__.__name__, "; ".join(descr)) + + +#: SUPPORTED_EXTENSIONS maps all supported extension names to their class. +#: This can be used to iterate all supported extensions of wsproto, instantiate +#: new extensions based on their name, or check if a given extension is +#: supported or not. +SUPPORTED_EXTENSIONS = {PerMessageDeflate.name: PerMessageDeflate} diff --git a/axios-example/lib/python3.10/site-packages/wsproto/frame_protocol.py b/axios-example/lib/python3.10/site-packages/wsproto/frame_protocol.py new file mode 100644 index 0000000..d13a769 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/frame_protocol.py @@ -0,0 +1,673 @@ +""" +wsproto/frame_protocol +~~~~~~~~~~~~~~~~~~~~~~ + +WebSocket frame protocol implementation. +""" + +import os +import struct +from codecs import getincrementaldecoder, IncrementalDecoder +from enum import IntEnum +from typing import Generator, List, NamedTuple, Optional, Tuple, TYPE_CHECKING, Union + +if TYPE_CHECKING: + from .extensions import Extension # pragma: no cover + + +_XOR_TABLE = [bytes(a ^ b for a in range(256)) for b in range(256)] + + +class XorMaskerSimple: + def __init__(self, masking_key: bytes) -> None: + self._masking_key = masking_key + + def process(self, data: bytes) -> bytes: + if data: + data_array = bytearray(data) + a, b, c, d = (_XOR_TABLE[n] for n in self._masking_key) + data_array[::4] = data_array[::4].translate(a) + data_array[1::4] = data_array[1::4].translate(b) + data_array[2::4] = data_array[2::4].translate(c) + data_array[3::4] = data_array[3::4].translate(d) + + # Rotate the masking key so that the next usage continues + # with the next key element, rather than restarting. + key_rotation = len(data) % 4 + self._masking_key = ( + self._masking_key[key_rotation:] + self._masking_key[:key_rotation] + ) + + return bytes(data_array) + return data + + +class XorMaskerNull: + def process(self, data: bytes) -> bytes: + return data + + +# RFC6455, Section 5.2 - Base Framing Protocol + +# Payload length constants +PAYLOAD_LENGTH_TWO_BYTE = 126 +PAYLOAD_LENGTH_EIGHT_BYTE = 127 +MAX_PAYLOAD_NORMAL = 125 +MAX_PAYLOAD_TWO_BYTE = 2**16 - 1 +MAX_PAYLOAD_EIGHT_BYTE = 2**64 - 1 +MAX_FRAME_PAYLOAD = MAX_PAYLOAD_EIGHT_BYTE + +# MASK and PAYLOAD LEN are packed into a byte +MASK_MASK = 0x80 +PAYLOAD_LEN_MASK = 0x7F + +# FIN, RSV[123] and OPCODE are packed into a single byte +FIN_MASK = 0x80 +RSV1_MASK = 0x40 +RSV2_MASK = 0x20 +RSV3_MASK = 0x10 +OPCODE_MASK = 0x0F + + +class Opcode(IntEnum): + """ + RFC 6455, Section 5.2 - Base Framing Protocol + """ + + #: Continuation frame + CONTINUATION = 0x0 + + #: Text message + TEXT = 0x1 + + #: Binary message + BINARY = 0x2 + + #: Close frame + CLOSE = 0x8 + + #: Ping frame + PING = 0x9 + + #: Pong frame + PONG = 0xA + + def iscontrol(self) -> bool: + return bool(self & 0x08) + + +class CloseReason(IntEnum): + """ + RFC 6455, Section 7.4.1 - Defined Status Codes + """ + + #: indicates a normal closure, meaning that the purpose for + #: which the connection was established has been fulfilled. + NORMAL_CLOSURE = 1000 + + #: indicates that an endpoint is "going away", such as a server + #: going down or a browser having navigated away from a page. + GOING_AWAY = 1001 + + #: indicates that an endpoint is terminating the connection due + #: to a protocol error. + PROTOCOL_ERROR = 1002 + + #: indicates that an endpoint is terminating the connection + #: because it has received a type of data it cannot accept (e.g., an + #: endpoint that understands only text data MAY send this if it + #: receives a binary message). + UNSUPPORTED_DATA = 1003 + + #: Reserved. The specific meaning might be defined in the future. + # DON'T DEFINE THIS: RESERVED_1004 = 1004 + + #: is a reserved value and MUST NOT be set as a status code in a + #: Close control frame by an endpoint. It is designated for use in + #: applications expecting a status code to indicate that no status + #: code was actually present. + NO_STATUS_RCVD = 1005 + + #: is a reserved value and MUST NOT be set as a status code in a + #: Close control frame by an endpoint. It is designated for use in + #: applications expecting a status code to indicate that the + #: connection was closed abnormally, e.g., without sending or + #: receiving a Close control frame. + ABNORMAL_CLOSURE = 1006 + + #: indicates that an endpoint is terminating the connection + #: because it has received data within a message that was not + #: consistent with the type of the message (e.g., non-UTF-8 [RFC3629] + #: data within a text message). + INVALID_FRAME_PAYLOAD_DATA = 1007 + + #: indicates that an endpoint is terminating the connection + #: because it has received a message that violates its policy. This + #: is a generic status code that can be returned when there is no + #: other more suitable status code (e.g., 1003 or 1009) or if there + #: is a need to hide specific details about the policy. + POLICY_VIOLATION = 1008 + + #: indicates that an endpoint is terminating the connection + #: because it has received a message that is too big for it to + #: process. + MESSAGE_TOO_BIG = 1009 + + #: indicates that an endpoint (client) is terminating the + #: connection because it has expected the server to negotiate one or + #: more extension, but the server didn't return them in the response + #: message of the WebSocket handshake. The list of extensions that + #: are needed SHOULD appear in the /reason/ part of the Close frame. + #: Note that this status code is not used by the server, because it + #: can fail the WebSocket handshake instead. + MANDATORY_EXT = 1010 + + #: indicates that a server is terminating the connection because + #: it encountered an unexpected condition that prevented it from + #: fulfilling the request. + INTERNAL_ERROR = 1011 + + #: Server/service is restarting + #: (not part of RFC6455) + SERVICE_RESTART = 1012 + + #: Temporary server condition forced blocking client's request + #: (not part of RFC6455) + TRY_AGAIN_LATER = 1013 + + #: is a reserved value and MUST NOT be set as a status code in a + #: Close control frame by an endpoint. It is designated for use in + #: applications expecting a status code to indicate that the + #: connection was closed due to a failure to perform a TLS handshake + #: (e.g., the server certificate can't be verified). + TLS_HANDSHAKE_FAILED = 1015 + + +# RFC 6455, Section 7.4.1 - Defined Status Codes +LOCAL_ONLY_CLOSE_REASONS = ( + CloseReason.NO_STATUS_RCVD, + CloseReason.ABNORMAL_CLOSURE, + CloseReason.TLS_HANDSHAKE_FAILED, +) + + +# RFC 6455, Section 7.4.2 - Status Code Ranges +MIN_CLOSE_REASON = 1000 +MIN_PROTOCOL_CLOSE_REASON = 1000 +MAX_PROTOCOL_CLOSE_REASON = 2999 +MIN_LIBRARY_CLOSE_REASON = 3000 +MAX_LIBRARY_CLOSE_REASON = 3999 +MIN_PRIVATE_CLOSE_REASON = 4000 +MAX_PRIVATE_CLOSE_REASON = 4999 +MAX_CLOSE_REASON = 4999 + + +NULL_MASK = struct.pack("!I", 0) + + +class ParseFailed(Exception): + def __init__( + self, msg: str, code: CloseReason = CloseReason.PROTOCOL_ERROR + ) -> None: + super().__init__(msg) + self.code = code + + +class RsvBits(NamedTuple): + rsv1: bool + rsv2: bool + rsv3: bool + + +class Header(NamedTuple): + fin: bool + rsv: RsvBits + opcode: Opcode + payload_len: int + masking_key: Optional[bytes] + + +class Frame(NamedTuple): + opcode: Opcode + payload: Union[bytes, str, Tuple[int, str]] + frame_finished: bool + message_finished: bool + + +def _truncate_utf8(data: bytes, nbytes: int) -> bytes: + if len(data) <= nbytes: + return data + + # Truncate + data = data[:nbytes] + # But we might have cut a codepoint in half, in which case we want to + # discard the partial character so the data is at least + # well-formed. This is a little inefficient since it processes the + # whole message twice when in theory we could just peek at the last + # few characters, but since this is only used for close messages (max + # length = 125 bytes) it really doesn't matter. + data = data.decode("utf-8", errors="ignore").encode("utf-8") + return data + + +class Buffer: + def __init__(self, initial_bytes: Optional[bytes] = None) -> None: + self.buffer = bytearray() + self.bytes_used = 0 + if initial_bytes: + self.feed(initial_bytes) + + def feed(self, new_bytes: bytes) -> None: + self.buffer += new_bytes + + def consume_at_most(self, nbytes: int) -> bytes: + if not nbytes: + return bytearray() + + data = self.buffer[self.bytes_used : self.bytes_used + nbytes] + self.bytes_used += len(data) + return data + + def consume_exactly(self, nbytes: int) -> Optional[bytes]: + if len(self.buffer) - self.bytes_used < nbytes: + return None + + return self.consume_at_most(nbytes) + + def commit(self) -> None: + # In CPython 3.4+, del[:n] is amortized O(n), *not* quadratic + del self.buffer[: self.bytes_used] + self.bytes_used = 0 + + def rollback(self) -> None: + self.bytes_used = 0 + + def __len__(self) -> int: + return len(self.buffer) + + +class MessageDecoder: + def __init__(self) -> None: + self.opcode: Optional[Opcode] = None + self.decoder: Optional[IncrementalDecoder] = None + + def process_frame(self, frame: Frame) -> Frame: + assert not frame.opcode.iscontrol() + + if self.opcode is None: + if frame.opcode is Opcode.CONTINUATION: + raise ParseFailed("unexpected CONTINUATION") + self.opcode = frame.opcode + elif frame.opcode is not Opcode.CONTINUATION: + raise ParseFailed("expected CONTINUATION, got %r" % frame.opcode) + + if frame.opcode is Opcode.TEXT: + self.decoder = getincrementaldecoder("utf-8")() + + finished = frame.frame_finished and frame.message_finished + + if self.decoder is None: + data = frame.payload + else: + assert isinstance(frame.payload, (bytes, bytearray)) + try: + data = self.decoder.decode(frame.payload, finished) + except UnicodeDecodeError as exc: + raise ParseFailed(str(exc), CloseReason.INVALID_FRAME_PAYLOAD_DATA) + + frame = Frame(self.opcode, data, frame.frame_finished, finished) + + if finished: + self.opcode = None + self.decoder = None + + return frame + + +class FrameDecoder: + def __init__( + self, client: bool, extensions: Optional[List["Extension"]] = None + ) -> None: + self.client = client + self.extensions = extensions or [] + + self.buffer = Buffer() + + self.header: Optional[Header] = None + self.effective_opcode: Optional[Opcode] = None + self.masker: Union[None, XorMaskerNull, XorMaskerSimple] = None + self.payload_required = 0 + self.payload_consumed = 0 + + def receive_bytes(self, data: bytes) -> None: + self.buffer.feed(data) + + def process_buffer(self) -> Optional[Frame]: + if not self.header: + if not self.parse_header(): + return None + # parse_header() sets these. + assert self.header is not None + assert self.masker is not None + assert self.effective_opcode is not None + + if len(self.buffer) < self.payload_required: + return None + + payload_remaining = self.header.payload_len - self.payload_consumed + payload = self.buffer.consume_at_most(payload_remaining) + if not payload and self.header.payload_len > 0: + return None + self.buffer.commit() + + self.payload_consumed += len(payload) + finished = self.payload_consumed == self.header.payload_len + + payload = self.masker.process(payload) + + for extension in self.extensions: + payload_ = extension.frame_inbound_payload_data(self, payload) + if isinstance(payload_, CloseReason): + raise ParseFailed("error in extension", payload_) + payload = payload_ + + if finished: + final = bytearray() + for extension in self.extensions: + result = extension.frame_inbound_complete(self, self.header.fin) + if isinstance(result, CloseReason): + raise ParseFailed("error in extension", result) + if result is not None: + final += result + payload += final + + frame = Frame(self.effective_opcode, payload, finished, self.header.fin) + + if finished: + self.header = None + self.effective_opcode = None + self.masker = None + else: + self.effective_opcode = Opcode.CONTINUATION + + return frame + + def parse_header(self) -> bool: + data = self.buffer.consume_exactly(2) + if data is None: + self.buffer.rollback() + return False + + fin = bool(data[0] & FIN_MASK) + rsv = RsvBits( + bool(data[0] & RSV1_MASK), + bool(data[0] & RSV2_MASK), + bool(data[0] & RSV3_MASK), + ) + opcode = data[0] & OPCODE_MASK + try: + opcode = Opcode(opcode) + except ValueError: + raise ParseFailed(f"Invalid opcode {opcode:#x}") + + if opcode.iscontrol() and not fin: + raise ParseFailed("Invalid attempt to fragment control frame") + + has_mask = bool(data[1] & MASK_MASK) + payload_len_short = data[1] & PAYLOAD_LEN_MASK + payload_len = self.parse_extended_payload_length(opcode, payload_len_short) + if payload_len is None: + self.buffer.rollback() + return False + + self.extension_processing(opcode, rsv, payload_len) + + if has_mask and self.client: + raise ParseFailed("client received unexpected masked frame") + if not has_mask and not self.client: + raise ParseFailed("server received unexpected unmasked frame") + if has_mask: + masking_key = self.buffer.consume_exactly(4) + if masking_key is None: + self.buffer.rollback() + return False + self.masker = XorMaskerSimple(masking_key) + else: + self.masker = XorMaskerNull() + + self.buffer.commit() + self.header = Header(fin, rsv, opcode, payload_len, None) + self.effective_opcode = self.header.opcode + if self.header.opcode.iscontrol(): + self.payload_required = payload_len + else: + self.payload_required = 0 + self.payload_consumed = 0 + return True + + def parse_extended_payload_length( + self, opcode: Opcode, payload_len: int + ) -> Optional[int]: + if opcode.iscontrol() and payload_len > MAX_PAYLOAD_NORMAL: + raise ParseFailed("Control frame with payload len > 125") + if payload_len == PAYLOAD_LENGTH_TWO_BYTE: + data = self.buffer.consume_exactly(2) + if data is None: + return None + (payload_len,) = struct.unpack("!H", data) + if payload_len <= MAX_PAYLOAD_NORMAL: + raise ParseFailed( + "Payload length used 2 bytes when 1 would have sufficed" + ) + elif payload_len == PAYLOAD_LENGTH_EIGHT_BYTE: + data = self.buffer.consume_exactly(8) + if data is None: + return None + (payload_len,) = struct.unpack("!Q", data) + if payload_len <= MAX_PAYLOAD_TWO_BYTE: + raise ParseFailed( + "Payload length used 8 bytes when 2 would have sufficed" + ) + if payload_len >> 63: + # I'm not sure why this is illegal, but that's what the RFC + # says, so... + raise ParseFailed("8-byte payload length with non-zero MSB") + + return payload_len + + def extension_processing( + self, opcode: Opcode, rsv: RsvBits, payload_len: int + ) -> None: + rsv_used = [False, False, False] + for extension in self.extensions: + result = extension.frame_inbound_header(self, opcode, rsv, payload_len) + if isinstance(result, CloseReason): + raise ParseFailed("error in extension", result) + for bit, used in enumerate(result): + if used: + rsv_used[bit] = True + for expected, found in zip(rsv_used, rsv): + if found and not expected: + raise ParseFailed("Reserved bit set unexpectedly") + + +class FrameProtocol: + def __init__(self, client: bool, extensions: List["Extension"]) -> None: + self.client = client + self.extensions = [ext for ext in extensions if ext.enabled()] + + # Global state + self._frame_decoder = FrameDecoder(self.client, self.extensions) + self._message_decoder = MessageDecoder() + self._parse_more = self._parse_more_gen() + + self._outbound_opcode: Optional[Opcode] = None + + def _process_close(self, frame: Frame) -> Frame: + data = frame.payload + assert isinstance(data, (bytes, bytearray)) + + if not data: + # "If this Close control frame contains no status code, _The + # WebSocket Connection Close Code_ is considered to be 1005" + data = (CloseReason.NO_STATUS_RCVD, "") + elif len(data) == 1: + raise ParseFailed("CLOSE with 1 byte payload") + else: + (code,) = struct.unpack("!H", data[:2]) + if code < MIN_CLOSE_REASON or code > MAX_CLOSE_REASON: + raise ParseFailed("CLOSE with invalid code") + try: + code = CloseReason(code) + except ValueError: + pass + if code in LOCAL_ONLY_CLOSE_REASONS: + raise ParseFailed("remote CLOSE with local-only reason") + if not isinstance(code, CloseReason) and code <= MAX_PROTOCOL_CLOSE_REASON: + raise ParseFailed("CLOSE with unknown reserved code") + try: + reason = data[2:].decode("utf-8") + except UnicodeDecodeError as exc: + raise ParseFailed( + "Error decoding CLOSE reason: " + str(exc), + CloseReason.INVALID_FRAME_PAYLOAD_DATA, + ) + data = (code, reason) + + return Frame(frame.opcode, data, frame.frame_finished, frame.message_finished) + + def _parse_more_gen(self) -> Generator[Optional[Frame], None, None]: + # Consume as much as we can from self._buffer, yielding events, and + # then yield None when we need more data. Or raise ParseFailed. + + # XX FIXME this should probably be refactored so that we never see + # disabled extensions in the first place... + self.extensions = [ext for ext in self.extensions if ext.enabled()] + closed = False + + while not closed: + frame = self._frame_decoder.process_buffer() + + if frame is not None: + if not frame.opcode.iscontrol(): + frame = self._message_decoder.process_frame(frame) + elif frame.opcode == Opcode.CLOSE: + frame = self._process_close(frame) + closed = True + + yield frame + + def receive_bytes(self, data: bytes) -> None: + self._frame_decoder.receive_bytes(data) + + def received_frames(self) -> Generator[Frame, None, None]: + for event in self._parse_more: + if event is None: + break + else: + yield event + + def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> bytes: + payload = bytearray() + if code is CloseReason.NO_STATUS_RCVD: + code = None + if code is None and reason: + raise TypeError("cannot specify a reason without a code") + if code in LOCAL_ONLY_CLOSE_REASONS: + code = CloseReason.NORMAL_CLOSURE + if code is not None: + payload += bytearray(struct.pack("!H", code)) + if reason is not None: + payload += _truncate_utf8( + reason.encode("utf-8"), MAX_PAYLOAD_NORMAL - 2 + ) + + return self._serialize_frame(Opcode.CLOSE, payload) + + def ping(self, payload: bytes = b"") -> bytes: + return self._serialize_frame(Opcode.PING, payload) + + def pong(self, payload: bytes = b"") -> bytes: + return self._serialize_frame(Opcode.PONG, payload) + + def send_data( + self, payload: Union[bytes, bytearray, str] = b"", fin: bool = True + ) -> bytes: + if isinstance(payload, (bytes, bytearray, memoryview)): + opcode = Opcode.BINARY + elif isinstance(payload, str): + opcode = Opcode.TEXT + payload = payload.encode("utf-8") + else: + raise ValueError("Must provide bytes or text") + + if self._outbound_opcode is None: + self._outbound_opcode = opcode + elif self._outbound_opcode is not opcode: + raise TypeError("Data type mismatch inside message") + else: + opcode = Opcode.CONTINUATION + + if fin: + self._outbound_opcode = None + + return self._serialize_frame(opcode, payload, fin) + + def _make_fin_rsv_opcode(self, fin: bool, rsv: RsvBits, opcode: Opcode) -> int: + fin_bits = int(fin) << 7 + rsv_bits = (int(rsv.rsv1) << 6) + (int(rsv.rsv2) << 5) + (int(rsv.rsv3) << 4) + opcode_bits = int(opcode) + + return fin_bits | rsv_bits | opcode_bits + + def _serialize_frame( + self, opcode: Opcode, payload: bytes = b"", fin: bool = True + ) -> bytes: + rsv = RsvBits(False, False, False) + for extension in reversed(self.extensions): + rsv, payload = extension.frame_outbound(self, opcode, rsv, payload, fin) + + fin_rsv_opcode = self._make_fin_rsv_opcode(fin, rsv, opcode) + + payload_length = len(payload) + quad_payload = False + if payload_length <= MAX_PAYLOAD_NORMAL: + first_payload = payload_length + second_payload = None + elif payload_length <= MAX_PAYLOAD_TWO_BYTE: + first_payload = PAYLOAD_LENGTH_TWO_BYTE + second_payload = payload_length + else: + first_payload = PAYLOAD_LENGTH_EIGHT_BYTE + second_payload = payload_length + quad_payload = True + + if self.client: + first_payload |= 1 << 7 + + header = bytearray([fin_rsv_opcode, first_payload]) + if second_payload is not None: + if opcode.iscontrol(): + raise ValueError("payload too long for control frame") + if quad_payload: + header += bytearray(struct.pack("!Q", second_payload)) + else: + header += bytearray(struct.pack("!H", second_payload)) + + if self.client: + # "The masking key is a 32-bit value chosen at random by the + # client. When preparing a masked frame, the client MUST pick a + # fresh masking key from the set of allowed 32-bit values. The + # masking key needs to be unpredictable; thus, the masking key + # MUST be derived from a strong source of entropy, and the masking + # key for a given frame MUST NOT make it simple for a server/proxy + # to predict the masking key for a subsequent frame. The + # unpredictability of the masking key is essential to prevent + # authors of malicious applications from selecting the bytes that + # appear on the wire." + # -- https://tools.ietf.org/html/rfc6455#section-5.3 + masking_key = os.urandom(4) + masker = XorMaskerSimple(masking_key) + return header + masking_key + masker.process(payload) + + return header + payload diff --git a/axios-example/lib/python3.10/site-packages/wsproto/handshake.py b/axios-example/lib/python3.10/site-packages/wsproto/handshake.py new file mode 100644 index 0000000..c456939 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/handshake.py @@ -0,0 +1,491 @@ +""" +wsproto/handshake +~~~~~~~~~~~~~~~~~~ + +An implementation of WebSocket handshakes. +""" +from collections import deque +from typing import ( + cast, + Deque, + Dict, + Generator, + Iterable, + List, + Optional, + Sequence, + Union, +) + +import h11 + +from .connection import Connection, ConnectionState, ConnectionType +from .events import AcceptConnection, Event, RejectConnection, RejectData, Request +from .extensions import Extension +from .typing import Headers +from .utilities import ( + generate_accept_token, + generate_nonce, + LocalProtocolError, + normed_header_dict, + RemoteProtocolError, + split_comma_header, +) + +# RFC6455, Section 4.2.1/6 - Reading the Client's Opening Handshake +WEBSOCKET_VERSION = b"13" + + +class H11Handshake: + """A Handshake implementation for HTTP/1.1 connections.""" + + def __init__(self, connection_type: ConnectionType) -> None: + self.client = connection_type is ConnectionType.CLIENT + self._state = ConnectionState.CONNECTING + + if self.client: + self._h11_connection = h11.Connection(h11.CLIENT) + else: + self._h11_connection = h11.Connection(h11.SERVER) + + self._connection: Optional[Connection] = None + self._events: Deque[Event] = deque() + self._initiating_request: Optional[Request] = None + self._nonce: Optional[bytes] = None + + @property + def state(self) -> ConnectionState: + return self._state + + @property + def connection(self) -> Optional[Connection]: + """Return the established connection. + + This will either return the connection or raise a + LocalProtocolError if the connection has not yet been + established. + + :rtype: h11.Connection + """ + return self._connection + + def initiate_upgrade_connection( + self, headers: Headers, path: Union[bytes, str] + ) -> None: + """Initiate an upgrade connection. + + This should be used if the request has already be received and + parsed. + + :param list headers: HTTP headers represented as a list of 2-tuples. + :param str path: A URL path. + """ + if self.client: + raise LocalProtocolError( + "Cannot initiate an upgrade connection when acting as the client" + ) + upgrade_request = h11.Request(method=b"GET", target=path, headers=headers) + h11_client = h11.Connection(h11.CLIENT) + self.receive_data(h11_client.send(upgrade_request)) + + def send(self, event: Event) -> bytes: + """Send an event to the remote. + + This will return the bytes to send based on the event or raise + a LocalProtocolError if the event is not valid given the + state. + + :returns: Data to send to the WebSocket peer. + :rtype: bytes + """ + data = b"" + if isinstance(event, Request): + data += self._initiate_connection(event) + elif isinstance(event, AcceptConnection): + data += self._accept(event) + elif isinstance(event, RejectConnection): + data += self._reject(event) + elif isinstance(event, RejectData): + data += self._send_reject_data(event) + else: + raise LocalProtocolError( + f"Event {event} cannot be sent during the handshake" + ) + return data + + def receive_data(self, data: Optional[bytes]) -> None: + """Receive data from the remote. + + A list of events that the remote peer triggered by sending + this data can be retrieved with :meth:`events`. + + :param bytes data: Data received from the WebSocket peer. + """ + self._h11_connection.receive_data(data or b"") + while True: + try: + event = self._h11_connection.next_event() + except h11.RemoteProtocolError: + raise RemoteProtocolError( + "Bad HTTP message", event_hint=RejectConnection() + ) + if ( + isinstance(event, h11.ConnectionClosed) + or event is h11.NEED_DATA + or event is h11.PAUSED + ): + break + + if self.client: + if isinstance(event, h11.InformationalResponse): + if event.status_code == 101: + self._events.append(self._establish_client_connection(event)) + else: + self._events.append( + RejectConnection( + headers=list(event.headers), + status_code=event.status_code, + has_body=False, + ) + ) + self._state = ConnectionState.CLOSED + elif isinstance(event, h11.Response): + self._state = ConnectionState.REJECTING + self._events.append( + RejectConnection( + headers=list(event.headers), + status_code=event.status_code, + has_body=True, + ) + ) + elif isinstance(event, h11.Data): + self._events.append( + RejectData(data=event.data, body_finished=False) + ) + elif isinstance(event, h11.EndOfMessage): + self._events.append(RejectData(data=b"", body_finished=True)) + self._state = ConnectionState.CLOSED + else: + if isinstance(event, h11.Request): + self._events.append(self._process_connection_request(event)) + + def events(self) -> Generator[Event, None, None]: + """Return a generator that provides any events that have been generated + by protocol activity. + + :returns: a generator that yields H11 events. + """ + while self._events: + yield self._events.popleft() + + # Server mode methods + + def _process_connection_request( # noqa: MC0001 + self, event: h11.Request + ) -> Request: + if event.method != b"GET": + raise RemoteProtocolError( + "Request method must be GET", event_hint=RejectConnection() + ) + connection_tokens = None + extensions: List[str] = [] + host = None + key = None + subprotocols: List[str] = [] + upgrade = b"" + version = None + headers: Headers = [] + for name, value in event.headers: + name = name.lower() + if name == b"connection": + connection_tokens = split_comma_header(value) + elif name == b"host": + host = value.decode("idna") + continue # Skip appending to headers + elif name == b"sec-websocket-extensions": + extensions.extend(split_comma_header(value)) + continue # Skip appending to headers + elif name == b"sec-websocket-key": + key = value + elif name == b"sec-websocket-protocol": + subprotocols.extend(split_comma_header(value)) + continue # Skip appending to headers + elif name == b"sec-websocket-version": + version = value + elif name == b"upgrade": + upgrade = value + headers.append((name, value)) + if connection_tokens is None or not any( + token.lower() == "upgrade" for token in connection_tokens + ): + raise RemoteProtocolError( + "Missing header, 'Connection: Upgrade'", event_hint=RejectConnection() + ) + if version != WEBSOCKET_VERSION: + raise RemoteProtocolError( + "Missing header, 'Sec-WebSocket-Version'", + event_hint=RejectConnection( + headers=[(b"Sec-WebSocket-Version", WEBSOCKET_VERSION)], + status_code=426 if version else 400, + ), + ) + if key is None: + raise RemoteProtocolError( + "Missing header, 'Sec-WebSocket-Key'", event_hint=RejectConnection() + ) + if upgrade.lower() != b"websocket": + raise RemoteProtocolError( + "Missing header, 'Upgrade: WebSocket'", event_hint=RejectConnection() + ) + if host is None: + raise RemoteProtocolError( + "Missing header, 'Host'", event_hint=RejectConnection() + ) + + self._initiating_request = Request( + extensions=extensions, + extra_headers=headers, + host=host, + subprotocols=subprotocols, + target=event.target.decode("ascii"), + ) + return self._initiating_request + + def _accept(self, event: AcceptConnection) -> bytes: + # _accept is always called after _process_connection_request. + assert self._initiating_request is not None + request_headers = normed_header_dict(self._initiating_request.extra_headers) + + nonce = request_headers[b"sec-websocket-key"] + accept_token = generate_accept_token(nonce) + + headers = [ + (b"Upgrade", b"WebSocket"), + (b"Connection", b"Upgrade"), + (b"Sec-WebSocket-Accept", accept_token), + ] + + if event.subprotocol is not None: + if event.subprotocol not in self._initiating_request.subprotocols: + raise LocalProtocolError(f"unexpected subprotocol {event.subprotocol}") + headers.append( + (b"Sec-WebSocket-Protocol", event.subprotocol.encode("ascii")) + ) + + if event.extensions: + accepts = server_extensions_handshake( + cast(Sequence[str], self._initiating_request.extensions), + event.extensions, + ) + if accepts: + headers.append((b"Sec-WebSocket-Extensions", accepts)) + + response = h11.InformationalResponse( + status_code=101, headers=headers + event.extra_headers + ) + self._connection = Connection( + ConnectionType.CLIENT if self.client else ConnectionType.SERVER, + event.extensions, + ) + self._state = ConnectionState.OPEN + return self._h11_connection.send(response) or b"" + + def _reject(self, event: RejectConnection) -> bytes: + if self.state != ConnectionState.CONNECTING: + raise LocalProtocolError( + "Connection cannot be rejected in state %s" % self.state + ) + + headers = list(event.headers) + if not event.has_body: + headers.append((b"content-length", b"0")) + response = h11.Response(status_code=event.status_code, headers=headers) + data = self._h11_connection.send(response) or b"" + self._state = ConnectionState.REJECTING + if not event.has_body: + data += self._h11_connection.send(h11.EndOfMessage()) or b"" + self._state = ConnectionState.CLOSED + return data + + def _send_reject_data(self, event: RejectData) -> bytes: + if self.state != ConnectionState.REJECTING: + raise LocalProtocolError( + f"Cannot send rejection data in state {self.state}" + ) + + data = self._h11_connection.send(h11.Data(data=event.data)) or b"" + if event.body_finished: + data += self._h11_connection.send(h11.EndOfMessage()) or b"" + self._state = ConnectionState.CLOSED + return data + + # Client mode methods + + def _initiate_connection(self, request: Request) -> bytes: + self._initiating_request = request + self._nonce = generate_nonce() + + headers = [ + (b"Host", request.host.encode("idna")), + (b"Upgrade", b"WebSocket"), + (b"Connection", b"Upgrade"), + (b"Sec-WebSocket-Key", self._nonce), + (b"Sec-WebSocket-Version", WEBSOCKET_VERSION), + ] + + if request.subprotocols: + headers.append( + ( + b"Sec-WebSocket-Protocol", + (", ".join(request.subprotocols)).encode("ascii"), + ) + ) + + if request.extensions: + offers: Dict[str, Union[str, bool]] = {} + for e in request.extensions: + assert isinstance(e, Extension) + offers[e.name] = e.offer() + extensions = [] + for name, params in offers.items(): + bname = name.encode("ascii") + if isinstance(params, bool): + if params: + extensions.append(bname) + else: + extensions.append(b"%s; %s" % (bname, params.encode("ascii"))) + if extensions: + headers.append((b"Sec-WebSocket-Extensions", b", ".join(extensions))) + + upgrade = h11.Request( + method=b"GET", + target=request.target.encode("ascii"), + headers=headers + request.extra_headers, + ) + return self._h11_connection.send(upgrade) or b"" + + def _establish_client_connection( + self, event: h11.InformationalResponse + ) -> AcceptConnection: # noqa: MC0001 + # _establish_client_connection is always called after _initiate_connection. + assert self._initiating_request is not None + assert self._nonce is not None + + accept = None + connection_tokens = None + accepts: List[str] = [] + subprotocol = None + upgrade = b"" + headers: Headers = [] + for name, value in event.headers: + name = name.lower() + if name == b"connection": + connection_tokens = split_comma_header(value) + continue # Skip appending to headers + elif name == b"sec-websocket-extensions": + accepts = split_comma_header(value) + continue # Skip appending to headers + elif name == b"sec-websocket-accept": + accept = value + continue # Skip appending to headers + elif name == b"sec-websocket-protocol": + subprotocol = value.decode("ascii") + continue # Skip appending to headers + elif name == b"upgrade": + upgrade = value + continue # Skip appending to headers + headers.append((name, value)) + + if connection_tokens is None or not any( + token.lower() == "upgrade" for token in connection_tokens + ): + raise RemoteProtocolError( + "Missing header, 'Connection: Upgrade'", event_hint=RejectConnection() + ) + if upgrade.lower() != b"websocket": + raise RemoteProtocolError( + "Missing header, 'Upgrade: WebSocket'", event_hint=RejectConnection() + ) + accept_token = generate_accept_token(self._nonce) + if accept != accept_token: + raise RemoteProtocolError("Bad accept token", event_hint=RejectConnection()) + if subprotocol is not None: + if subprotocol not in self._initiating_request.subprotocols: + raise RemoteProtocolError( + f"unrecognized subprotocol {subprotocol}", + event_hint=RejectConnection(), + ) + extensions = client_extensions_handshake( + accepts, cast(Sequence[Extension], self._initiating_request.extensions) + ) + + self._connection = Connection( + ConnectionType.CLIENT if self.client else ConnectionType.SERVER, + extensions, + self._h11_connection.trailing_data[0], + ) + self._state = ConnectionState.OPEN + return AcceptConnection( + extensions=extensions, extra_headers=headers, subprotocol=subprotocol + ) + + def __repr__(self) -> str: + return "{}(client={}, state={})".format( + self.__class__.__name__, self.client, self.state + ) + + +def server_extensions_handshake( + requested: Iterable[str], supported: List[Extension] +) -> Optional[bytes]: + """Agree on the extensions to use returning an appropriate header value. + + This returns None if there are no agreed extensions + """ + accepts: Dict[str, Union[bool, bytes]] = {} + for offer in requested: + name = offer.split(";", 1)[0].strip() + for extension in supported: + if extension.name == name: + accept = extension.accept(offer) + if isinstance(accept, bool): + if accept: + accepts[extension.name] = True + elif accept is not None: + accepts[extension.name] = accept.encode("ascii") + + if accepts: + extensions: List[bytes] = [] + for name, params in accepts.items(): + name_bytes = name.encode("ascii") + if isinstance(params, bool): + assert params + extensions.append(name_bytes) + else: + if params == b"": + extensions.append(b"%s" % (name_bytes)) + else: + extensions.append(b"%s; %s" % (name_bytes, params)) + return b", ".join(extensions) + + return None + + +def client_extensions_handshake( + accepted: Iterable[str], supported: Sequence[Extension] +) -> List[Extension]: + # This raises RemoteProtocolError is the accepted extension is not + # supported. + extensions = [] + for accept in accepted: + name = accept.split(";", 1)[0].strip() + for extension in supported: + if extension.name == name: + extension.finalize(accept) + extensions.append(extension) + break + else: + raise RemoteProtocolError( + f"unrecognized extension {name}", event_hint=RejectConnection() + ) + return extensions diff --git a/axios-example/lib/python3.10/site-packages/wsproto/py.typed b/axios-example/lib/python3.10/site-packages/wsproto/py.typed new file mode 100644 index 0000000..f5642f7 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/py.typed @@ -0,0 +1 @@ +Marker diff --git a/axios-example/lib/python3.10/site-packages/wsproto/typing.py b/axios-example/lib/python3.10/site-packages/wsproto/typing.py new file mode 100644 index 0000000..a44b27e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/typing.py @@ -0,0 +1,3 @@ +from typing import List, Tuple + +Headers = List[Tuple[bytes, bytes]] diff --git a/axios-example/lib/python3.10/site-packages/wsproto/utilities.py b/axios-example/lib/python3.10/site-packages/wsproto/utilities.py new file mode 100644 index 0000000..7cf53d1 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/wsproto/utilities.py @@ -0,0 +1,88 @@ +""" +wsproto/utilities +~~~~~~~~~~~~~~~~~ + +Utility functions that do not belong in a separate module. +""" +import base64 +import hashlib +import os +from typing import Dict, List, Optional, Union + +from h11._headers import Headers as H11Headers + +from .events import Event +from .typing import Headers + +# RFC6455, Section 1.3 - Opening Handshake +ACCEPT_GUID = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + + +class ProtocolError(Exception): + pass + + +class LocalProtocolError(ProtocolError): + """Indicates an error due to local/programming errors. + + This is raised when the connection is asked to do something that + is either incompatible with the state or the websocket standard. + + """ + + pass # noqa + + +class RemoteProtocolError(ProtocolError): + """Indicates an error due to the remote's actions. + + This is raised when processing the bytes from the remote if the + remote has sent data that is incompatible with the websocket + standard. + + .. attribute:: event_hint + + This is a suggested wsproto Event to send to the client based + on the error. It could be None if no hint is available. + + """ + + def __init__(self, message: str, event_hint: Optional[Event] = None) -> None: + self.event_hint = event_hint + super().__init__(message) + + +# Some convenience utilities for working with HTTP headers +def normed_header_dict(h11_headers: Union[Headers, H11Headers]) -> Dict[bytes, bytes]: + # This mangles Set-Cookie headers. But it happens that we don't care about + # any of those, so it's OK. For every other HTTP header, if there are + # multiple instances then you're allowed to join them together with + # commas. + name_to_values: Dict[bytes, List[bytes]] = {} + for name, value in h11_headers: + name_to_values.setdefault(name, []).append(value) + name_to_normed_value = {} + for name, values in name_to_values.items(): + name_to_normed_value[name] = b", ".join(values) + return name_to_normed_value + + +# We use this for parsing the proposed protocol list, and for parsing the +# proposed and accepted extension lists. For the proposed protocol list it's +# fine, because the ABNF is just 1#token. But for the extension lists, it's +# wrong, because those can contain quoted strings, which can in turn contain +# commas. XX FIXME +def split_comma_header(value: bytes) -> List[str]: + return [piece.decode("ascii").strip() for piece in value.split(b",")] + + +def generate_nonce() -> bytes: + # os.urandom may be overkill for this use case, but I don't think this + # is a bottleneck, and better safe than sorry... + return base64.b64encode(os.urandom(16)) + + +def generate_accept_token(token: bytes) -> bytes: + accept_token = token + ACCEPT_GUID + accept_token = hashlib.sha1(accept_token).digest() + return base64.b64encode(accept_token) diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/INSTALLER b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/LICENSE b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/LICENSE new file mode 100644 index 0000000..353924b --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/LICENSE @@ -0,0 +1,19 @@ +Copyright Jason R. Coombs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/METADATA b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/METADATA new file mode 100644 index 0000000..94e90a0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/METADATA @@ -0,0 +1,84 @@ +Metadata-Version: 2.1 +Name: zipp +Version: 3.8.0 +Summary: Backport of pathlib-compatible object wrapper for zip files +Home-page: https://github.com/jaraco/zipp +Author: Jason R. Coombs +Author-email: jaraco@jaraco.com +License: UNKNOWN +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Requires-Python: >=3.7 +License-File: LICENSE +Provides-Extra: docs +Requires-Dist: sphinx ; extra == 'docs' +Requires-Dist: jaraco.packaging (>=9) ; extra == 'docs' +Requires-Dist: rst.linker (>=1.9) ; extra == 'docs' +Provides-Extra: testing +Requires-Dist: pytest (>=6) ; extra == 'testing' +Requires-Dist: pytest-checkdocs (>=2.4) ; extra == 'testing' +Requires-Dist: pytest-flake8 ; extra == 'testing' +Requires-Dist: pytest-cov ; extra == 'testing' +Requires-Dist: pytest-enabler (>=1.0.1) ; extra == 'testing' +Requires-Dist: jaraco.itertools ; extra == 'testing' +Requires-Dist: func-timeout ; extra == 'testing' +Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing' +Requires-Dist: pytest-mypy (>=0.9.1) ; (platform_python_implementation != "PyPy") and extra == 'testing' + +.. image:: https://img.shields.io/pypi/v/zipp.svg + :target: `PyPI link`_ + +.. image:: https://img.shields.io/pypi/pyversions/zipp.svg + :target: `PyPI link`_ + +.. _PyPI link: https://pypi.org/project/zipp + +.. image:: https://github.com/jaraco/zipp/workflows/tests/badge.svg + :target: https://github.com/jaraco/zipp/actions?query=workflow%3A%22tests%22 + :alt: tests + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + :alt: Code style: Black + +.. .. image:: https://readthedocs.org/projects/skeleton/badge/?version=latest +.. :target: https://skeleton.readthedocs.io/en/latest/?badge=latest + +.. image:: https://img.shields.io/badge/skeleton-2022-informational + :target: https://blog.jaraco.com/skeleton + + +A pathlib-compatible Zipfile object wrapper. Official backport of the standard library +`Path object `_. + + +Compatibility +============= + +New features are introduced in this third-party library and later merged +into CPython. The following table indicates which versions of this library +were contributed to different versions in the standard library: + +.. list-table:: + :header-rows: 1 + + * - zipp + - stdlib + * - 3.5 + - 3.11 + * - 3.3 + - 3.9 + * - 1.0 + - 3.8 + + +Usage +===== + +Use ``zipp.Path`` in place of ``zipfile.Path`` on any Python. + + diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/RECORD b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/RECORD new file mode 100644 index 0000000..218aae9 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/RECORD @@ -0,0 +1,9 @@ +__pycache__/zipp.cpython-310.pyc,, +zipp-3.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +zipp-3.8.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050 +zipp-3.8.0.dist-info/METADATA,sha256=6KJo2_gKMNYNz52FNbITlpwbHwa_st0KWpNMFB9OQfE,2719 +zipp-3.8.0.dist-info/RECORD,, +zipp-3.8.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +zipp-3.8.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +zipp-3.8.0.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5 +zipp.py,sha256=5hrx38_-kX0WCpfBk5LSwCIMYraThjaNj5HsriUSB-8,8029 diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/REQUESTED b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/WHEEL b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/top_level.txt b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/top_level.txt new file mode 100644 index 0000000..e82f676 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp-3.8.0.dist-info/top_level.txt @@ -0,0 +1 @@ +zipp diff --git a/axios-example/lib/python3.10/site-packages/zipp.py b/axios-example/lib/python3.10/site-packages/zipp.py new file mode 100644 index 0000000..52c82a0 --- /dev/null +++ b/axios-example/lib/python3.10/site-packages/zipp.py @@ -0,0 +1,312 @@ +import io +import posixpath +import zipfile +import itertools +import contextlib +import pathlib + + +__all__ = ['Path'] + + +def _parents(path): + """ + Given a path with elements separated by + posixpath.sep, generate all parents of that path. + + >>> list(_parents('b/d')) + ['b'] + >>> list(_parents('/b/d/')) + ['/b'] + >>> list(_parents('b/d/f/')) + ['b/d', 'b'] + >>> list(_parents('b')) + [] + >>> list(_parents('')) + [] + """ + return itertools.islice(_ancestry(path), 1, None) + + +def _ancestry(path): + """ + Given a path with elements separated by + posixpath.sep, generate all elements of that path + + >>> list(_ancestry('b/d')) + ['b/d', 'b'] + >>> list(_ancestry('/b/d/')) + ['/b/d', '/b'] + >>> list(_ancestry('b/d/f/')) + ['b/d/f', 'b/d', 'b'] + >>> list(_ancestry('b')) + ['b'] + >>> list(_ancestry('')) + [] + """ + path = path.rstrip(posixpath.sep) + while path and path != posixpath.sep: + yield path + path, tail = posixpath.split(path) + + +_dedupe = dict.fromkeys +"""Deduplicate an iterable in original order""" + + +def _difference(minuend, subtrahend): + """ + Return items in minuend not in subtrahend, retaining order + with O(1) lookup. + """ + return itertools.filterfalse(set(subtrahend).__contains__, minuend) + + +class CompleteDirs(zipfile.ZipFile): + """ + A ZipFile subclass that ensures that implied directories + are always included in the namelist. + """ + + @staticmethod + def _implied_dirs(names): + parents = itertools.chain.from_iterable(map(_parents, names)) + as_dirs = (p + posixpath.sep for p in parents) + return _dedupe(_difference(as_dirs, names)) + + def namelist(self): + names = super(CompleteDirs, self).namelist() + return names + list(self._implied_dirs(names)) + + def _name_set(self): + return set(self.namelist()) + + def resolve_dir(self, name): + """ + If the name represents a directory, return that name + as a directory (with the trailing slash). + """ + names = self._name_set() + dirname = name + '/' + dir_match = name not in names and dirname in names + return dirname if dir_match else name + + @classmethod + def make(cls, source): + """ + Given a source (filename or zipfile), return an + appropriate CompleteDirs subclass. + """ + if isinstance(source, CompleteDirs): + return source + + if not isinstance(source, zipfile.ZipFile): + return cls(source) + + # Only allow for FastLookup when supplied zipfile is read-only + if 'r' not in source.mode: + cls = CompleteDirs + + source.__class__ = cls + return source + + +class FastLookup(CompleteDirs): + """ + ZipFile subclass to ensure implicit + dirs exist and are resolved rapidly. + """ + + def namelist(self): + with contextlib.suppress(AttributeError): + return self.__names + self.__names = super(FastLookup, self).namelist() + return self.__names + + def _name_set(self): + with contextlib.suppress(AttributeError): + return self.__lookup + self.__lookup = super(FastLookup, self)._name_set() + return self.__lookup + + +class Path: + """ + A pathlib-compatible interface for zip files. + + Consider a zip file with this structure:: + + . + ├── a.txt + └── b + ├── c.txt + └── d + └── e.txt + + >>> data = io.BytesIO() + >>> zf = zipfile.ZipFile(data, 'w') + >>> zf.writestr('a.txt', 'content of a') + >>> zf.writestr('b/c.txt', 'content of c') + >>> zf.writestr('b/d/e.txt', 'content of e') + >>> zf.filename = 'mem/abcde.zip' + + Path accepts the zipfile object itself or a filename + + >>> root = Path(zf) + + From there, several path operations are available. + + Directory iteration (including the zip file itself): + + >>> a, b = root.iterdir() + >>> a + Path('mem/abcde.zip', 'a.txt') + >>> b + Path('mem/abcde.zip', 'b/') + + name property: + + >>> b.name + 'b' + + join with divide operator: + + >>> c = b / 'c.txt' + >>> c + Path('mem/abcde.zip', 'b/c.txt') + >>> c.name + 'c.txt' + + Read text: + + >>> c.read_text() + 'content of c' + + existence: + + >>> c.exists() + True + >>> (b / 'missing.txt').exists() + False + + Coercion to string: + + >>> import os + >>> str(c).replace(os.sep, posixpath.sep) + 'mem/abcde.zip/b/c.txt' + + At the root, ``name``, ``filename``, and ``parent`` + resolve to the zipfile. Note these attributes are not + valid and will raise a ``ValueError`` if the zipfile + has no filename. + + >>> root.name + 'abcde.zip' + >>> str(root.filename).replace(os.sep, posixpath.sep) + 'mem/abcde.zip' + >>> str(root.parent) + 'mem' + """ + + __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" + + def __init__(self, root, at=""): + """ + Construct a Path from a ZipFile or filename. + + Note: When the source is an existing ZipFile object, + its type (__class__) will be mutated to a + specialized type. If the caller wishes to retain the + original type, the caller should either create a + separate ZipFile object or pass a filename. + """ + self.root = FastLookup.make(root) + self.at = at + + def open(self, mode='r', *args, pwd=None, **kwargs): + """ + Open this entry as text or binary following the semantics + of ``pathlib.Path.open()`` by passing arguments through + to io.TextIOWrapper(). + """ + if self.is_dir(): + raise IsADirectoryError(self) + zip_mode = mode[0] + if not self.exists() and zip_mode == 'r': + raise FileNotFoundError(self) + stream = self.root.open(self.at, zip_mode, pwd=pwd) + if 'b' in mode: + if args or kwargs: + raise ValueError("encoding args invalid for binary operation") + return stream + return io.TextIOWrapper(stream, *args, **kwargs) + + @property + def name(self): + return pathlib.Path(self.at).name or self.filename.name + + @property + def suffix(self): + return pathlib.Path(self.at).suffix or self.filename.suffix + + @property + def suffixes(self): + return pathlib.Path(self.at).suffixes or self.filename.suffixes + + @property + def stem(self): + return pathlib.Path(self.at).stem or self.filename.stem + + @property + def filename(self): + return pathlib.Path(self.root.filename).joinpath(self.at) + + def read_text(self, *args, **kwargs): + with self.open('r', *args, **kwargs) as strm: + return strm.read() + + def read_bytes(self): + with self.open('rb') as strm: + return strm.read() + + def _is_child(self, path): + return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") + + def _next(self, at): + return self.__class__(self.root, at) + + def is_dir(self): + return not self.at or self.at.endswith("/") + + def is_file(self): + return self.exists() and not self.is_dir() + + def exists(self): + return self.at in self.root._name_set() + + def iterdir(self): + if not self.is_dir(): + raise ValueError("Can't listdir a file") + subs = map(self._next, self.root.namelist()) + return filter(self._is_child, subs) + + def __str__(self): + return posixpath.join(self.root.filename, self.at) + + def __repr__(self): + return self.__repr.format(self=self) + + def joinpath(self, *other): + next = posixpath.join(self.at, *other) + return self._next(self.root.resolve_dir(next)) + + __truediv__ = joinpath + + @property + def parent(self): + if not self.at: + return self.filename.parent + parent_at = posixpath.dirname(self.at.rstrip('/')) + if parent_at: + parent_at += '/' + return self._next(parent_at) diff --git a/axios-example/meta.json b/axios-example/meta.json new file mode 100644 index 0000000..50fa2fd --- /dev/null +++ b/axios-example/meta.json @@ -0,0 +1 @@ +{"0": "Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.", "1": "Vaast Colson (\u00b01977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...", "2": "Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis \u2014 Antwerp. 10 September \u2014 6 November 2005. Exhibition.", "3": "Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.", "4": "Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.", "5": "Vaast Colson and Kati Heck \u201cShow me yours & I'll show you mine\u201d at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2\u2032. Share.", "6": "Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.", "7": "The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...", "8": "Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...", "9": "'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...", "10": "Apr 13, 2022 \u2014 Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...", "11": "vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...", "12": "About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...", "13": "Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque \u00b7 ATP DIARY \u00b7 2 Minutes \u00b7 Talks \u00b7 Art Text \u00b7 Artist's Diary \u00b7 Colophon \u00b7 Contact ...", "14": "MOREPublishers present Quest Object by Vaast Colson, Stadslimiet, Antwerp, BE 2013 - Het verzamelen voorbij (presentation of Colson's private collection of ...", "15": "Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...", "16": "Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.", "17": "Vaast Colson: \u00b7 \"N 50\u00b053'41,47\u201d\u2013 E 4\u00b020'29,48\u201d\" \u00b7 \"You used to be part of something (public poster edition)\" \u00b7 \"SIZING & RESIZING - All sound intentions and then ...", "18": "w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...", "19": "Kunsthuis Yellowart - curator Vaast Colson. \u201cIk stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...", "20": "Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.", "21": "Vaast Colson. Webring. Arte.Go.it \u00b7 Arte.Go.Shop \u00b7 dgPixel Multimedia \u00b7 TechShop \u00b7 TechBlog \u00b7 Redazione Cultura \u00b7 WordPress Area Test", "22": "Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Aud\u00e9oud, Vaast Colson, ...", "23": "Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...", "24": "Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...", "25": "Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.", "26": "35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: \u201cVaast Colson #muhka #vaastcolson #antwerp\u201d", "27": "Mar 25, 2015 - Vaast Colson, 'Break Down the Wall' (2006) Colson opened up a hole in the wall between Maes & Matthijs Gallery and Stella Lohaus Gallery.", "28": "artist, Figure 87: Vaast Colson. term, eternal network / la f\u00eate permanente. year, 2016. courtesy of, Courtesy of the artist \u00a9 M HKA.", "29": "Vaast Colson. Save. Cancel. Delete. Events \u00b7 Edit \u00b7 Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam \u00b7 The Image Generator. 29 Jan - 01 Feb 2015.", "30": "Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...", "31": "... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.", "32": "Tag: Vaast Colson. Arocha and S. Schraenen, Circa Tabac (detail), 2007 / J. G. Pinsel. \u201cSanguine \u2013 Luc Tuymans on Baroque\u201d at Fondazione Prada.", "33": "Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions \u00b7 Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.", "34": "In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...", "35": "Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...", "36": "Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,", "37": "AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.", "38": "Marc Nagtzaam \u00b7 Fabienne Aud\u00e9oud \u00b7 Christine Meisner \u00b7 Vaast Colson \u00b7 Mekhitar Garabedian \u00b7 Raymond Pettibon \u00b7 Javier T\u00e9llez \u00b7 Abraham Cruzvillegas.", "39": "IAC \u2014 Institut d'art contemporain \u2014 Villeurbanne/Rh\u00f4ne-Alpes.", "40": "Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...", "41": "Oct 4, 2021 \u2014 Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.", "42": "Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.", "43": "een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, \u2026 a frank conversation with Vaast ...", "44": "Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.", "45": "Vaast Colson \u00b7 Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. \u00b7 Schrijf ...", "46": "FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Opening. Performance. 22 02 2009 00:00 01:00. Watch the video of the performance ...", "47": "Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...", "48": "Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.", "49": "Apr 19, 2009 \u2014 In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...", "50": "In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...", "51": "Feb 19, 2016 \u2014 Vaast Colson (Kapellen, 1977 \u2013 lives and works in Antwerp) is known for his versatile visual work that includes sculptures, installations, ...", "52": "Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...", "53": "Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...", "54": "Oct 7, 2020 \u2014 Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...", "55": "In 2001 galoppeerde Vaast Colson (\u00b01977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...", "56": "Vaast Colson. museum notebook. Hardcover | Nederlands. \u20ac 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.", "57": "Vaast Colson. Schwarzer Peter \u2014 das Original. 20.12.2019 \u2014 21.12.2019. Presentatie van de editie: VAAST COLSON, \u201c ...", "58": "[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...", "59": "Aug 25, 2013 \u2014 Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving \u2013 the synthesis of the 12 portraits \u2013 at which you can sit to make ...", "60": "May 15, 2015 \u2014 Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...", "61": "Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.", "62": "Consultez les coordonn\u00e9es, dirigeants et chiffres-cl\u00e9s de VAAST COLSON FOUNDATION (0892.660.019) \u00e0 Antwerpen (2018) et d'autres soci\u00e9t\u00e9s du secteur Art, ...", "63": "Recyclart et JAP s'associent une fois de plus, \u00e0 Chapelle cette fois, et pr\u00e9sentent ensemble une exposition de l'artiste Vaast Colson.", "64": "Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR\u00ae) are reserved by the ...", "65": "Drop by on 3 December for an artist talk with Vaast Colson. With works by Aur\u00e9lie Bayad \u2013 Oona Bovri \u2013 Vaast Colson \u2013 Marijke De Roover \u2013 Messieurs Delmotte \u2013 ...", "66": "Oct 20, 2019 \u2014 Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...", "67": "Auteur, Tekst, In, Jaar. [tijdschrift] Ons Erfdeel, 'Portfolio Urszula Antoniak Gust Van den Berghe Rik Wouters Vaast Colson Vis \u00e0 Vis Peter Pontiac Abraham ...", "68": "PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...", "69": "Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].", "70": "Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material \u2013 on artist. Maes & Matthys Gallery, 2009.", "71": "VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.", "72": "CIAP is een centrum voor actuele kunst gevestigd in Hasselt, Belgi\u00eb.", "73": "KUNSTFORUM International \u00b7 Home \u203a Recherche \u203a Vaast Colson. KUNSTFORUM International. 1 Artikelergebniss(e) zu \u201eColson, Vaast\u201c ...", "74": "Sep 12, 2022 \u2014 Bid now on Invaluable: VAAST COLSON (\u00b01977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.", "75": "Flickriver - view images as a 'river of photos' and more...", "76": "Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).", "77": "2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...", "78": "Jun 27, 2015 \u2014 Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.", "79": "Mar 24, 2012 \u2014 Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...", "80": "Bekijk contactgegevens, directieleden en kerncijfers van VAAST COLSON FOUNDATION (0892.660.019) uit Antwerpen (2018) en andere bedrijven uit de sector Kunst ...", "81": "Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...", "82": "Sigtryggur Berg Sigmarsson / Vaast Colson. Peter Fengler / Kim Gordon / Dennis Tyfus. Joris van de Moortel. INTERPUNCTION #5 / Koen Delaere.", "83": "Jun 27, 2015 \u2014 Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...", "84": "Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...", "85": "Feb 27, 2016 \u2014 Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...", "86": "Sep 24, 2009 \u2014 Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.", "87": "Vaast Colson. Artista. Naci\u00f3 en 1977 en Kapellen, Antwerpen, B\u00e9lgica. Reside en B\u00e9lgica.", "88": "Vaast Colson. Agenda \u00b7 20 jaar Ultra Eczema \u00b7 SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...", "89": "Colson, Vaast. Author(s): Title: Publication year: Publication place: Publisher: Edition: Pages: Dimensions: Binding: Specifications:", "90": "Apr 3, 2018 \u2014 Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...", "91": "Vaast Colson runs his own fan club from the castle as a true modern- day knight. Pictured is Fabian. M\u00e9relle's \"Chevalier\". Other works from the collection.", "92": "Dec 4, 2015 \u2014 Het resultaat is een heel gevarieerde en boeiende selectie, een bonte afwisseling van kleurrijke verhalen. Foto boven: Portret Vaast Colson & ...", "93": "Vaast Colson. We beschikken over \u00e9\u00e9n enkel grafisch werk van deze kunstenaar. Werken in de collectie (voor de technische ...", "94": "Vaast Colson.", "95": "Madame Adolie FUMIERE. de Saint-Vaast (7100, Belgique). + 16-08-29 - 08-12-22. P.F.Colson & Mony-Fleurs. Partager. Annonce. Condol\u00e9ances.", "96": "Madame Adolie FUMIERE. de Saint-Vaast (7100). + 16-08-29 - 09-12-22. P.F.Colson & Mony-Fleurs. Partager. Annonce. Condol\u00e9ances. Je consulte les condol\u00e9ances ...", "97": "Madame Adolie FUMIERE. de Saint-Vaast (7100). + 16-08-29 - 09-12-22. P.F.Colson & Mony-Fleurs. Partager. Annonce. Condol\u00e9ances. Je consulte les condol\u00e9ances ..."} \ No newline at end of file diff --git a/axios-example/meta.py b/axios-example/meta.py new file mode 100644 index 0000000..52c300e --- /dev/null +++ b/axios-example/meta.py @@ -0,0 +1,57 @@ +import selenium +from selenium import webdriver +from selenium.webdriver.common.by import By +import time +import requests +import os +import io +import multiprocessing +import json + +DRIVER_PATH = '../geckodriver' +DRIVER_PATH2 = '../chromedriver' + +def meta(queries,wd3): + url = 'https://www.google.it/search?q=vaast+colson&sxsrf=ALiCzsYcMyMvNo67pjpN-zRgfmTXw1L6Zw%3A1670252242664&source=hp&ei=0gaOY7zUJfbjxc8Pu_2QmAE&iflsig=AJiK0e8AAAAAY44U4oHBLhsJUz-SOp-oMy5eO2PMIDLU&gs_ssp=eJzj4tVP1zc0TDKvMDJMqjQzYPTiKUtMLC5RSM7PKc7PAwB8eAkY&oq=vaast+colsan&gs_lcp=Cgdnd3Mtd2l6EAEYADIHCC4QgAQQDTIGCAAQHhANMgYIABAeEA0yBggAEB4QDTIGCAAQHhANMggIABAIEB4QDToECCMQJzoLCC4QgAQQxwEQ0QM6CAguENQCEIAEOggILhCABBDUAjoFCAAQgAQ6BQguEIAEOgsILhCABBDHARCvAToOCC4QgAQQxwEQ0QMQ1AI6CAguEIAEEMsBOggIABCABBDLAToLCC4Q1AIQgAQQywE6DgguEK8BEMcBEIAEEMsBOgoIABCABBAKEMsBOgcIABCABBAKOgYIABAWEB46CAgAEBYQHhAKOgUIABCGA1AAWMkOYK0XaAFwAHgBgAHhAogB-RKSAQcxLjYuNS4xmAEAoAEB&sclient=gws-wiz' + wd3.get(url) + wd3.find_element(By.ID,'W0wltc').click() + + dictionary = open('meta.json',) + l = json.load(dictionary) + + print(l) + print('jsonjson!') + + i=2 + n = 0 + + while True: + try: + wd3.find_element(By.CSS_SELECTOR, "a[aria-label='Page {}']".format(i)).click() + searchResults = wd3.find_elements(By.CLASS_NAME, 'VwiC3b') + + + for result in searchResults: + #l = '' + l[n] = result.text + time.sleep(.5) + + print(l) + + n=n+1 + with open("meta.json", "w") as outfile: + json.dump(l, outfile) + + time.sleep(.5) + + #wd2.execute_script(f"document.querySelector('#text').innerHTML += {result.text}") + print("Navigating to Next Page " + str(i)) + i=i+1 + time.sleep(1) + except: + print("Last page reached") + break + +wd3 = webdriver.Chrome(executable_path=DRIVER_PATH2) +queries = ["VAAST COLSON"] +meta(queries,wd3) \ No newline at end of file diff --git a/axios-example/pics.json b/axios-example/pics.json new file mode 100644 index 0000000..202dde0 --- /dev/null +++ b/axios-example/pics.json @@ -0,0 +1,251 @@ +{ + "0": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU", + "1": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU", + "2": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU", + "3": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU", + "4": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU", + "5": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU", + "6": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRA5B6YzNZRMdifODu-gphOdDydfMzIARaBpw&usqp=CAU", + "7": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU", + "8": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU", + "9": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU", + "10": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU", + "11": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU", + "12": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU", + "13": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU", + "14": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU", + "15": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU", + "16": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU", + "17": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU", + "18": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU", + "19": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU", + "20": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU", + "21": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU", + "22": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU", + "23": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU", + "24": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU", + "25": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU", + "26": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU", + "27": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU", + "28": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU", + "29": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU", + "30": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU", + "31": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU", + "32": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU", + "33": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU", + "34": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU", + "35": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU", + "36": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU", + "37": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU", + "38": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU", + "39": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU", + "40": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU", + "41": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU", + "42": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU", + "43": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU", + "44": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU", + "45": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU", + "46": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU", + "47": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU", + "48": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU", + "49": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU", + "50": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU", + "51": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU", + "52": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU", + "53": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU", + "54": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU", + "55": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU", + "56": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU", + "57": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU", + "58": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU", + "59": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU", + "60": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR64TGDt2ff6d_oGdvcFl7HOT_v93wP22ldKA&usqp=CAU", + "61": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU", + "62": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU", + "63": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU", + "64": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU", + "65": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU", + "66": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU", + "67": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU", + "68": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU", + "69": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU", + "70": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU", + "71": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU", + "72": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU", + "73": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU", + "74": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU", + "75": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU", + "76": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTu-1EahSgwRf6_16tr19RDei327hsXtktZcg&usqp=CAU", + "77": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU", + "78": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU", + "79": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU", + "80": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkrZ9hXY50BcluytHRQzIKZmLNhvCC-xyYBc4e7SenmFrwIGEPbjhck7i1FrDVWlT993c&usqp=CAU", + "81": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYH9QpQccvE4PG6ny68p1BhBx8ceLiimfQrqr5L_ZLaj68_HBMSaf4bU8M3f318yvfG8&usqp=CAU", + "82": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSI7WkpI7XOe7OLgpSYxSxZUNkjjqw9myp_lznG0vGoPCPk_u31MUu46cL5EF1dFh0nxFk&usqp=CAU", + "83": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRs6ja7Tq1NkRci6FhGbO2WN5g5bz0dcMns37yDThdKy0tPtzSwpH_832cryCbtCpK3XHY&usqp=CAU", + "84": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSRr3Ej11lIGq85WZ7KIONRl4zhBUPpZEkhFMU1R1dZzCTWQJBaUzz41zj03tihXzPldw4&usqp=CAU", + "85": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRny43WofbHnNhpGp9j-aZzFmmfCxjRvq6HtfJfFWvZRKjyuXk4LCYl5D3uk-eCeTtuzqQ&usqp=CAU", + "86": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqgo1DsADmzyZ2WnQ13ETdSlPledS5VflmV7hR4iuO8fY2v-B24tivYJqkNZcoJ42ereo&usqp=CAU", + "87": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRhRGcvKQ82X1d9_WLQw8k4Jrh11QLgF8i2KOQz57eeEbCK58fzz0MFYlWARSONrL39Ag&usqp=CAU", + "88": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS0HypeWCAhPpFAbJ84uekit5FkIYinovWB2ynwaXFRcEGDRMhJTfomS0yNFZqQxxlnsc4&usqp=CAU", + "89": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQESxXhhB7MVuxNPCnWD_X6mgqBMMpqaUiq2RVgrQ_u4QyZ-Zv6-KzSfKBoWtT_1Zn3M5A&usqp=CAU", + "90": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRrv7ujmQVAYaDG9j9SZA4ArhDKFs4LRKObtlo0pO-w0pM1cf4qp9T4ausA1BFGOg4YwZg&usqp=CAU", + "91": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ4M6NJP-9EQduJ84NsKfiCTumjyG5o_AdLrwPn0d3ng0-ZtZTwwSQtBU6Bok9ClL81JbM&usqp=CAU", + "92": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJZdlR9pbrQ9NcNGZ3kSocsaHSFtIKZTobyufHH2jymgajlzrL6et7gNKypb3_Fnf1RIo&usqp=CAU", + "93": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQeeM3eJRYM0iIKQV7s7aKaRtugQv7p9vaJVfq22YV2Mp4t53CMvKRHnFiwXvV3UuXCIiI&usqp=CAU", + "94": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT1S7tuE1msU5c4HZV55EXsHodIbUpoqf5fj-GS-fHef5zkYtpVb8uMHIi4mpqA6iCCMq4&usqp=CAU", + "95": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9SqYifMyZ0JunVdmDfRegc-G6PBSGaBTv9BSdKy40rvu2IW9GKJeln6ZXw5Wvw1mQTDs&usqp=CAU", + "96": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTY6WhFfn4n_M7zxvZrPnZ6dpGt_Vds_KlvSexn4BCLADvDEcCDzbT_nzBY4ONaI32qJTw&usqp=CAU", + "97": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdbgb-vkziPEVaV1AD90hliuUUEJqpwCCCCwCQkMQ4flNNCpG21G-w6E1czNvMqFve6ao&usqp=CAU", + "98": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTzg0fFrE-oaXM0iVyGSwiOQYyBYBfNfPDk6sEKnljIw8U2aOKMg0SviCWrYcE1DB5x48A&usqp=CAU", + "99": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmklkBjGn8-vOvZDW6MIYWbl4AB8vB6-5zW1HIbAlkZAqvtbyp4ueVnr31pba2JSGLI6g&usqp=CAU", + "100": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRIjjeEvePntcVN2QuimRv00J_SmoqhMQt6zQ&usqp=CAU", + "101": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRCFsk2r5PODfINsC_9GmClRJ8vLqp9tTAb_w&usqp=CAU", + "102": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQLm5XVcUlwE0mYpfULTOnCh1cfNPv_iP2t7g&usqp=CAU", + "103": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRytjjA6cyYPI7jjODg7nU6kIb__afXQ3WBPA&usqp=CAU", + "104": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRc6X7VPOVP0mhAwCVIXlQhd1J_4hTn6jRcqw&usqp=CAU", + "105": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8QgubrxEuV7tV3d-iSbXi4mS79-QyYB0Kig&usqp=CAU", + "106": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzTV1iSzVr9Y9eswADXf3IGkQ5-GpCrBgDaQ&usqp=CAU", + "107": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbLUY_GpI8vLtnjDuEeGXOpUUSbI1_41kgyQ&usqp=CAU", + "108": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoas6x28nB-DfSWm7q5yVk_X2i_5vsEs0hNw&usqp=CAU", + "109": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTvR_Kh1glzoOatIKyKJhyg9dOotvOxAIxIrQ&usqp=CAU", + "110": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTih2tHkZg6enF8zuNEWYicbmkelCUSnks9tQ&usqp=CAU", + "111": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFy9QzW3lN-mibGlX1HTC_8ZQcoz_WvMuH1g&usqp=CAU", + "112": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSG3K2Z0-zKcl6KfnIkMUWI2GXsgPRmAlQWPg&usqp=CAU", + "113": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpvEZWlKMi6BjJ9H-xdS3WgEjJ4ZdODS0nYg&usqp=CAU", + "114": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ6varwXIes8UWB4NiRxyrR6XvQS2ja0akEOg&usqp=CAU", + "115": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFxcU3BzbJbBPXkRzh6sXvrfX5FkXDPVzMgQ&usqp=CAU", + "116": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYPpXEGFyxj0uSW0XkYcyRSGDRzzRCR0grxg&usqp=CAU", + "117": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsgC9GIqTXnqPtyKc6Cs6lI62wD4pc8XDJCg&usqp=CAU", + "118": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwvbzPMKTT1upzYgDT_tox4nfVSrwd1n4RoA&usqp=CAU", + "119": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNajCGwakMfXVVTTQMt8wtf6YAOhpq4jx1VA&usqp=CAU", + "120": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQV1S91maiP-C4vzLIC_vGUYimqr1E8bn7rxw&usqp=CAU", + "121": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-P1IKKg-KD9Oh3kwQwfVtHJnSfRfsBuDhFQ&usqp=CAU", + "122": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNi5B-SxuD_mMdqIGCi06OaG4gIDEuD0mF3g&usqp=CAU", + "123": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh_ikOZ2uH0OreJMC7Z1lTcUiVQING-VeIvw&usqp=CAU", + "124": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuw7-CCOFdb2zXe3Tc_dnbMq6DWMS6LsLxuw&usqp=CAU", + "125": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXqkhu8V5DmWazrp3Oi1vnUIQzxa8zNuveJA&usqp=CAU", + "126": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLxa9tVzkosh7udU53CJF-gFNpNkiwkr8R9Q&usqp=CAU", + "127": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRdfQzmqqEo43RQTJvgylfdZmYkpTVSwKLALQ&usqp=CAU", + "128": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAiNwcKYNwjSO1KYBHfdVhjSUD1Nlwat--og&usqp=CAU", + "129": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcScWiB0qmrq1EO00HRv2wugJQOdDVL6jsnJgA&usqp=CAU", + "130": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_2t8DNIYM3FDXBaZzKsc84H8k9qalTQmNMg&usqp=CAU", + "131": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbzTwm03eicgyJ5mQTpWSbqpZnMc-zV91RjA&usqp=CAU", + "132": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQoAdeORPsqvD_hRNu7GnT-7ZjaDDeP3PPlw&usqp=CAU", + "133": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRsvjnRbqv6Fb4IoSerY_DKL13aLetgvFj4CA&usqp=CAU", + "134": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQP4im01HJvCQ3Mb6--ilO02ZJ2gD78j-XlzA&usqp=CAU", + "135": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJ9hMmPualV1xiscBZKfYwIH7LT-hxG_HKGw&usqp=CAU", + "136": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSjcC-QBOngGrfyoHYUsXbdn-MtDC2yBJDqOw&usqp=CAU", + "137": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSfkpTF904XmF8d2Krl_QeNLYmk5DhSyeWJA&usqp=CAU", + "138": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSP9DsORW16a053wwfxl2K5F3-3v9-cW_nXeQ&usqp=CAU", + "139": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSudw5QQ3vmB0UbvLNMRAbvTSjSBxnEl-G2jg&usqp=CAU", + "140": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSpDnHDWiekEmL7prA-w7OwcZfCJhj0NTKGw&usqp=CAU", + "141": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUIjRupmR0QP6L7fau1UT8q_Ilw_zKswZi3A&usqp=CAU", + "142": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSMhgBBVtyFiIZYKbchwqtlnf-R0i-y8LJ6kA&usqp=CAU", + "143": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQwRJlo__ltilwtR2D_6uufz8lGbOrVnNFVKQ&usqp=CAU", + "144": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSlLxfkCIKD3i_PBGjqWQJlp72RzHUD1KvA_w&usqp=CAU", + "145": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSA45GYQFl0Ko7fNzeEqpTwQGmk8zW_9LV1ng&usqp=CAU", + "146": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRL1EeTf6sTJJOrnXguF-9YjmB14j7o1MRdjQ&usqp=CAU", + "147": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAu4dYhJL32aXRUxJKJC4GpLKNekLDbPxUBQ&usqp=CAU", + "148": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpPj2Xjzv02svymH1xKmtHwsC22PEAFoLcmQ&usqp=CAU", + "149": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRQf0fCyjg4vzOczzcomunZT5wk1LbHya3qTA&usqp=CAU", + "150": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSMYm8AMVwdFxG_g30_u6Nw7gpCMvqVGb5JYg&usqp=CAU", + "151": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQwJb8px21Z4V3Z-fIl_y33TUaDlWxUxwPmEA&usqp=CAU", + "152": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdF6kXiofrcXiMyrLLRODsRe09v4ifKdZ4jg&usqp=CAU", + "153": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBU2L9XwPOJWa_z-GFJgt9ntd1SSQ1y835cw&usqp=CAU", + "154": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqYWfgwbvxQy_hi7rS3-kuR8Rb9_SO3QspaQ&usqp=CAU", + "155": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjt8hI1yJj9RB4xbfWpFiCvGSCuv8LNtgOSg&usqp=CAU", + "156": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAN3I3i9cjaVh_fM8P4hyjjT1nppMly4nHXQ&usqp=CAU", + "157": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTlE-2ard1gxmekxjUaESqp7qQyRPzVGzjyug&usqp=CAU", + "158": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRD7i7SviGTXxAvO6Hp3Wzp6CauQSXD_CYCEw&usqp=CAU", + "159": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRMx1vpitw7az3JApZG5azshVMhD2vkk-XD0w&usqp=CAU", + "160": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQN2u_jHCz-cCc5v4HJ6xVRW98ttSyLZ-hodw&usqp=CAU", + "161": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQRWq4vtmIMXt7RKENmr5X5lcNOhRL6PzEQg&usqp=CAU", + "162": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQ_zT723jLpkHNhAtxM-0jzuo1KvqOvN9mVw&usqp=CAU", + "163": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhhmFWu9lCiMjduwtPZVdTj7wPuLMczprUEw&usqp=CAU", + "164": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR51QQ6V3IGAz5sFssx4GFfwPJnSVbTopl_-w&usqp=CAU", + "165": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS5kVED2pKtGavcd7xQJ9_EE-Rp3cQh5rPsTw&usqp=CAU", + "166": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmcim5iUpgxdf7Ggiq_AAoP6yjCUSjfG-L2A&usqp=CAU", + "167": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSnh7Em06jR9TGM8mmu-CMxbqp0N7aD55Q1jQ&usqp=CAU", + "168": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQB0M2aYhRAnWWZL1ID0ndNz0FxojtqYSCZ6A&usqp=CAU", + "169": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTq4medtOuzYpHGb22aHQIYSf-LpHWCUyGJ8A&usqp=CAU", + "170": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRI4ezjLdOvQtBusl9NIANPzkRD2cxUDSUvVA&usqp=CAU", + "171": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTAUVFUrS9yMgSHimpKXUEdK9YK2LRDfSmzSg&usqp=CAU", + "172": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSygRLnf27CNEccUgxb9rcddo1argImCCfNNA&usqp=CAU", + "173": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQChMNDSjvoz13y3PJYoMdkFstsPZsR6PKs0g&usqp=CAU", + "174": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRHR6R2N9RpU1HvCX5Rvq1XyR_8rSlqHmPWQQ&usqp=CAU", + "175": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRwxwfitUiMvmCAHnzvbTgoCcLkSwSPf519Zg&usqp=CAU", + "176": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZcnvemZrceyQiht2inAFdA-KNqkA1q3IAaA&usqp=CAU", + "177": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFsYoFDB8HkdsFHTrW5Xu9L-irlIsWQBBt_Q&usqp=CAU", + "178": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQOdd_TP6FUroT_Fm1QEHHIEHzRi-XGHiksmQ&usqp=CAU", + "179": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQLsroH69Yk1G12k-iVXomuSstLRcQmHB44DA&usqp=CAU", + "180": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS446_Qm8_O2lJfWXvek4zZSMuOOUzR4J1fXcCzp47hdW2D3RH9KNG0dZZVfvGFDOAv3jc&usqp=CAU", + "181": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrxPiicOU3b-nM9_CO_oOTyMvhX5Kr4XtuKO--f61UAtY0fAksPmRawkRfewLSJjinhmc&usqp=CAU", + "182": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRn-FENIZ7i-Do-EMfI-fcjcUNu0yfcnJr6bwsMkMhtNAsuZXOFdHrarA6rl7b66orYn_U&usqp=CAU", + "183": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZoFOJMS7qZQDPlJMo1ZHI2pBJ3TeHgbQZeVVsDlRINfuUhFGWIsLZJMqEz45T3i8Upig&usqp=CAU", + "184": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTR3pdoUVmj0fpvXU485XEUfpUQTrU_IwdtSmbavdz1VcfwYBwJsCa8YS1QA1cCDY2M-mY&usqp=CAU", + "185": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTELZ4dmWXkkZqDRM92mdoQj__wpQX_WQpdRxUREY2HJNiKcwDk18EwP0Nytid02gPb-Rw&usqp=CAU", + "186": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkKkIW3_O6sh76P5hPGxyaP0jxDBs2L_mxdihi-yurplbTYUBoe4uQb7Sl3joOWNl_bzk&usqp=CAU", + "187": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPXBETDGiKnA89MO-Pc2zu8B7qiKvfbAIJO-Bp5kgg6UyIMj8P4P0u29XpSA9HykwJl1M&usqp=CAU", + "188": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSK_nyBGdTgPXCWWds1K5kUsjEyfxMEgeqnLmVDgu6Ig25gIl64BplKMweMBL6eEqzb1QQ&usqp=CAU", + "189": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFhv7Vfri-mxq52QGbcZumaQnumRivIINiK5xhxqIVKSdHBYNrQI5ZTEsuIfdNzfRdjhY&usqp=CAU", + "190": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYLW-WKd3hcI66V2natiYsZVnNgcSQvTgboJLBrsr1nAjV1YPg_Fy0a2odOQKRYuPNbxk&usqp=CAU", + "191": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTA_L2k5L-Zd24cAjW_CQ7BBTIXF5Kzuk75rwshcxypHfdkN7iYrnzHTTiensDbm5Rs7C0&usqp=CAU", + "192": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNYNm6xyQ_2F0PT1530mT9nj1WpkMfRGPKoA9y5dP7WwIk-tDqnJzjylZ-PmdDD5d3dQA&usqp=CAU", + "193": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQMUPPAupAatr6rMJL_MZrOci6yBtBtMDsO-67GSOEZBVQkftaq33qmoQ82RBR_Dei5w4&usqp=CAU", + "194": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS09ugMOP3eEbse9DQeF37vcOrq4VGKo8xbeAwXrEOqB_HaZ6aZcT-FV7VbdFUeUNNAQxs&usqp=CAU", + "195": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR_ohIrdxvA30fSXVM-zOAQcIYMgXYPb4R_VFNzc4NvhlGEuZZdLV5bqMohh8tYJUhbmzM&usqp=CAU", + "196": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTiR6IK7TMPRfUWCvVR9qO5zJBoZDs1C-gxamXa5O1_Pckj1GxOoULPll4rb7p96lrcgA&usqp=CAU", + "197": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFARvOrqz2JfVwf-DbHMTQr5XrlBQH95f0VgSXnBlHOXU9Kh0Zj2xNvuMSwbAjR9PXPio&usqp=CAU", + "198": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT5N6n-CjhKo1DGoSADV0yJMVOGC4b0hrMjYenUYQgxZ_ejhnY2VA4AR8U0V2WORW6M7FM&usqp=CAU", + "199": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS5SXUTEuNv7nGeRxBDSszkOrH45LiyjWXM3qAlm1q4Z63XoedBICsBgWaqBVXR3Z1D36o&usqp=CAU", + "200": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTm5YONb07T7om7WUgF4XQW6XS3XUuvhrstew&usqp=CAU", + "201": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqa9B9MGmQA6BOPv9dBqspffT66hj8LIE5Qw&usqp=CAU", + "202": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcToOOUYFl9FJM8WKMnYxjb0n4sF_pOUIMRjBQ&usqp=CAU", + "203": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRr1WlHqMzSDQvNhl6dZ0tCAcHbetAx7hMtA&usqp=CAU", + "204": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTL94eCu4Hos6lI4Hi6zrEPmvN2ce5UTTqWKw&usqp=CAU", + "205": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ4ID5ksWlO9aVdQegu1eyY0x3oseOtq70Fpg&usqp=CAU", + "206": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBeBJdxjwSxAswREy56t7X1Y9hhwm0wQvHyg&usqp=CAU", + "207": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQnW4gWjmfPY5HP0Qi2U8D8Wip6ndVmV1Db6g&usqp=CAU", + "208": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2bO07B6Be7kkNmIoa11SWMW9rb6S2M5umpw&usqp=CAU", + "209": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTE2cUkuRh5NSCetbS6Prd1Wo2I_mC_cvkBA&usqp=CAU", + "210": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSwHhumy-e8YdukspnP49gedYrzJttYPpdTqg&usqp=CAU", + "211": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUN1eMCQg9DQax9AyQlWarDiI0BWeTft69Rg&usqp=CAU", + "212": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRh-jfSlOpnXQIfDommsI2xu57gKep9HKKEWw&usqp=CAU", + "213": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRkv664Wjm9hegkESpsQhSdhdODuG-4L7PbGg&usqp=CAU", + "214": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSgW7yxnCwRaUllQRtabdvSYIkXqGd_dNBXQ&usqp=CAU", + "215": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzkWtLrWffgsX9xWXe6WbZ5BaBRVKljKAj3w&usqp=CAU", + "216": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRj5q8Tyq-5EvMPBobmNF5xS66IXUx0fmF67Q&usqp=CAU", + "217": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS9kkWOnv78RQ36n5UbJrhFPYd_zcAF-QAisg&usqp=CAU", + "218": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkbVs1NeY1HTvDLJm1gY1gfT_ZXlB2TXx_Iw&usqp=CAU", + "219": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCaXTiacllL_Dk4Xu9QcZ-KcVhYFkfp8dgUw&usqp=CAU", + "220": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjLFhmG_ubB50vjxSDT1EcnI06-PK87tNig&usqp=CAU", + "221": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTURu-lQ83Fejd_N7tdGjvUz1dsGiaxByj--A&usqp=CAU", + "222": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFPbkMbj1bBZwBLiVEAIuH54bJOHBaM5899g&usqp=CAU", + "223": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKkrNZavEgRuJLI-Dvo7ATJH7PNh5onSNZFw&usqp=CAU", + "224": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTcJ36tsHa4Sroti8Usvj3oYC0q0WSgOW4sjw&usqp=CAU", + "225": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR56f3R6gDj278Sl93XvlMfoqCl_FHhfVtwcQ&usqp=CAU", + "226": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTltpjD4-U2EQeLzYmGPQaXm3UIpele07TYeA&usqp=CAU", + "227": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSL9yjZ9LwzE92ETGfI_zyGOe2EfqbckuK2dA&usqp=CAU", + "228": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRswNNTciOpEuTRqGOv-7sv5kw3p7zQdaqfag&usqp=CAU", + "229": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzyFXFYoTtaESNrTRmSry8wfntI7sDi1jwzg&usqp=CAU", + "230": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-IRqDRyCVCq0thJOVrNFnrHxQGLhvqQ8bHA&usqp=CAU", + "231": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRMFGOVW91vstwXskuFCxjOqVHO73CDQaS7cQ&usqp=CAU", + "232": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRUwXavji0Ie5iNX1kMSXv9eWtUeEIiNRSRYw&usqp=CAU", + "233": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRX5tAcGX-TD3nAOHTTi_ha87wHYoMd7CHXtA&usqp=CAU", + "234": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ5Xn9N2oJcx34F6zZa4-k8wlXOpScVb2Vs6w&usqp=CAU", + "235": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAu8oVArGEj18PKjoZYzfJzIzXYlasdhC5Pg&usqp=CAU", + "236": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRCSkwO8JlmSLw2kNzA8zmYTZhkRks_MTcmFQ&usqp=CAU", + "237": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRpMw4_vH0omugTiti0b1-zbZxQLTiMQJZv9A&usqp=CAU", + "238": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRG6EPa897dodBklqHXXtPRtn_KtVaBk7Jocw&usqp=CAU", + "239": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk6N659iKR-unGUBRvZXm34tpG3-soueFB-A&usqp=CAU", + "240": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS4aDeXyE00EDVKsG9W-0kyu0NhQWjJj6f4-Q&usqp=CAU", + "241": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRo2M5300aaecvpS6imVhBWj5_DpsTlrtw3FA&usqp=CAU", + "242": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSD5VZEQGtwRVyZs9DO09WJwvP_qcDAb3Zx-A&usqp=CAU", + "243": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5LfpsoCcUmCcjb0MWuXPyRyiAHWlHQ72Elg&usqp=CAU", + "244": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZird4UNmqgzXykLt1HTvFH8565P1EZUTBdg&usqp=CAU", + "245": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmhhW_45BBGF5wFjeO3ozjETYyeaDB9eSq-w&usqp=CAU", + "246": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbgZx8Hqe7gp83a2QIznzDF7z6QnE7gbJDig&usqp=CAU", + "247": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCr3wtKLD8lZY-_0hYhF2UxTywkE_vJvIwXA&usqp=CAU", + "248": "https://www.flacc.info/assets/images/gen/gallery_2531.jpg" +} \ No newline at end of file diff --git a/axios-example/pics.py b/axios-example/pics.py new file mode 100644 index 0000000..cf1482d --- /dev/null +++ b/axios-example/pics.py @@ -0,0 +1,120 @@ +import selenium +from selenium import webdriver +from selenium.webdriver.common.by import By +import time +import requests +import os +import io +import json +import random +import json + +DRIVER_PATH = '../geckodriver' +DRIVER_PATH2 = '../chromedriver' + + +def harvesting(query:str, max_links_to_fetch:int, wd:webdriver, sleep_between_interactions:int=1): + dictionary = open('pics.json',) + l = json.load(dictionary) + + cycles = 10 + + def scroll_to_end(wd): + wd.execute_script("window.scrollTo(0, document.body.scrollHeight);") + time.sleep(sleep_between_interactions) + + # build the google query + search_url = "https://www.google.com/search?safe=off&site=&tbm=isch&source=hp&q={q}&oq={q}&gs_l=img" + + # load the page + wd.get(search_url.format(q=query)) + + image_urls = set() + image_count = 0 + results_start = 0 + + sx ="sx" + dx="dx" + + + while image_count < max_links_to_fetch: + for loop in range(cycles): + scroll_to_end(wd) + time.sleep(.1) + + # get all image thumbnail results + thumbnail_results = wd.find_elements(By.CLASS_NAME,"Q4LuWd") + number_results = len(thumbnail_results) + print(f"Found: {number_results} search results. Extracting links from {results_start}:{number_results}") + + # some useful variables + nPic = 0 + holdPic=0 + groundPic = 0 + currentMeta = '' + + + for img in thumbnail_results[results_start:number_results]: + # click the thumbnail to get the actual image + try: + img.click() + time.sleep(.1) + except Exception: + continue + + # extract image url + actual_images = wd.find_elements(By.CLASS_NAME,'n3VNCb') + actual_image = actual_images[-1] + if actual_image.get_attribute('src') and 'http' in actual_image.get_attribute('src'): + image_urls.add(actual_image.get_attribute('src')) + linkPic = actual_image.get_attribute('src') + # + # print(linkPic) + + l[nPic] = linkPic + time.sleep(.2) + + # print(l) + + + with open("pics.json", "w") as outfile: + json.dump(l, outfile) + + nPic = nPic+1 + + holdPic = holdPic+1 + time.sleep(.2) + + image_count = len(image_urls) + + if len(image_urls) >= max_links_to_fetch: + print(f"Found: {len(image_urls)} image links, done!") + break + else: + print("Found:", len(image_urls), "image links, looking for more ...") + time.sleep(1) + return + load_more_button = wd.find_element(By.CLASS_NAME,"Mye4qd") + if load_more_button: + wd.execute_script("document.querySelector('.mye4qd').click();") + + # move the result startpoint further down + results_start = len(thumbnail_results) + + return image_urls + +if __name__ == '__main__': + wd = webdriver.Firefox(executable_path=DRIVER_PATH) + query = "VAAST COLSON" + wd.get('https://google.com') + time.sleep(.3) + wd.find_element(By.ID,'W0wltc').click() + + time.sleep(.5) + + search_box = wd.find_element(By.CLASS_NAME,'gLFyf') + search_box.send_keys(query) + + links = harvesting(query,2000,wd) + + wd.quit() \ No newline at end of file diff --git a/axios-example/pyvenv.cfg b/axios-example/pyvenv.cfg new file mode 100644 index 0000000..cc66556 --- /dev/null +++ b/axios-example/pyvenv.cfg @@ -0,0 +1,3 @@ +home = /usr/local/opt/python@3.10/bin +include-system-site-packages = false +version = 3.10.8 diff --git a/axios-example/requirements.txt b/axios-example/requirements.txt new file mode 100644 index 0000000..ff8b2d2 --- /dev/null +++ b/axios-example/requirements.txt @@ -0,0 +1,8 @@ +click==8.1.3 +Flask==2.1.2 +importlib-metadata==4.11.4 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.1 +Werkzeug==2.1.2 +zipp==3.8.0 diff --git a/axios-example/static/style.css b/axios-example/static/style.css new file mode 100644 index 0000000..68a211c --- /dev/null +++ b/axios-example/static/style.css @@ -0,0 +1,3154 @@ +:root { + --scenePerspective: 1; + --scenePerspectiveOriginX: 50; + --scenePerspectiveOriginY: 0; + --itemZ: 2; + --cameraSpeed: 20; + --cameraZ: 0; + --viewportHeight: 105; +} + +.viewport { + height: calc(var(--viewportHeight) * 1px); +} +.viewport .scene3D-container { + z-index: 1; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + perspective: calc(var(--scenePerspective) * var(--cameraSpeed) * 1px); + perspective-origin: calc(var(--scenePerspectiveOriginX) * 1%) calc(var(--scenePerspectiveOriginY) * 1%); + will-change: perspective-origin; + transform: translate3d(0, 0, 0); +} +.viewport .scene3D-container .scene3D { + position: absolute; + top: 0; + height: 100vh; + width: 100%; + transform-style: preserve-3d; + transform: translateZ(calc(var(--cameraZ) * 1px)); + will-change: transform; +} +.viewport .scene3D-container .scene3D > div { + position: absolute; + display: block; + width: 70%; + top: 100%; +} +.viewport .scene3D-container .scene3D > div:nth-child(2n) { + left: 80%; + bottom: 10%; +} +.viewport .scene3D-container .scene3D > div:nth-child(2n+1) { + right: 80%; + bottom: 10%; +} +.viewport .scene3D-container .scene3D > div:nth-child(0) { + transform: translate3D(14.3%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 0 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(1) { + transform: translate3D(7.6%, 43%, calc(var(--itemZ) * var(--cameraSpeed) * 1 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(2) { + transform: translate3D(18.7%, 178%, calc(var(--itemZ) * var(--cameraSpeed) * 2 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(3) { + transform: translate3D(17.6%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 3 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(4) { + transform: translate3D(14%, 194%, calc(var(--itemZ) * var(--cameraSpeed) * 4 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(5) { + transform: translate3D(13.1%, 215%, calc(var(--itemZ) * var(--cameraSpeed) * 5 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(6) { + transform: translate3D(3.3%, 168%, calc(var(--itemZ) * var(--cameraSpeed) * 6 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(7) { + transform: translate3D(4.3%, 41%, calc(var(--itemZ) * var(--cameraSpeed) * 7 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(8) { + transform: translate3D(6.8%, 138%, calc(var(--itemZ) * var(--cameraSpeed) * 8 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(9) { + transform: translate3D(3%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 9 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(10) { + transform: translate3D(2.5%, 118%, calc(var(--itemZ) * var(--cameraSpeed) * 10 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(11) { + transform: translate3D(17%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 11 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(12) { + transform: translate3D(1.3%, 88%, calc(var(--itemZ) * var(--cameraSpeed) * 12 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(13) { + transform: translate3D(4.7%, 30%, calc(var(--itemZ) * var(--cameraSpeed) * 13 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(14) { + transform: translate3D(2.4%, 145%, calc(var(--itemZ) * var(--cameraSpeed) * 14 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(15) { + transform: translate3D(19.2%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 15 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(16) { + transform: translate3D(18.1%, 104%, calc(var(--itemZ) * var(--cameraSpeed) * 16 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(17) { + transform: translate3D(4.1%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 17 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(18) { + transform: translate3D(8.4%, 243%, calc(var(--itemZ) * var(--cameraSpeed) * 18 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(19) { + transform: translate3D(13.6%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 19 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(20) { + transform: translate3D(18.2%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 20 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(21) { + transform: translate3D(12%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 21 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(22) { + transform: translate3D(18.5%, 131%, calc(var(--itemZ) * var(--cameraSpeed) * 22 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(23) { + transform: translate3D(8.4%, 231%, calc(var(--itemZ) * var(--cameraSpeed) * 23 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(24) { + transform: translate3D(4.3%, 82%, calc(var(--itemZ) * var(--cameraSpeed) * 24 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(25) { + transform: translate3D(6.7%, 192%, calc(var(--itemZ) * var(--cameraSpeed) * 25 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(26) { + transform: translate3D(7.7%, 81%, calc(var(--itemZ) * var(--cameraSpeed) * 26 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(27) { + transform: translate3D(15.7%, 195%, calc(var(--itemZ) * var(--cameraSpeed) * 27 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(28) { + transform: translate3D(11.3%, 134%, calc(var(--itemZ) * var(--cameraSpeed) * 28 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(29) { + transform: translate3D(6.4%, 40%, calc(var(--itemZ) * var(--cameraSpeed) * 29 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(30) { + transform: translate3D(1.1%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 30 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(31) { + transform: translate3D(2.6%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 31 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(32) { + transform: translate3D(12.6%, 88%, calc(var(--itemZ) * var(--cameraSpeed) * 32 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(33) { + transform: translate3D(17.3%, 23%, calc(var(--itemZ) * var(--cameraSpeed) * 33 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(34) { + transform: translate3D(4.9%, 30%, calc(var(--itemZ) * var(--cameraSpeed) * 34 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(35) { + transform: translate3D(18.3%, 67%, calc(var(--itemZ) * var(--cameraSpeed) * 35 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(36) { + transform: translate3D(7%, 122%, calc(var(--itemZ) * var(--cameraSpeed) * 36 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(37) { + transform: translate3D(3.8%, 211%, calc(var(--itemZ) * var(--cameraSpeed) * 37 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(38) { + transform: translate3D(12.3%, 177%, calc(var(--itemZ) * var(--cameraSpeed) * 38 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(39) { + transform: translate3D(10.5%, 280%, calc(var(--itemZ) * var(--cameraSpeed) * 39 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(40) { + transform: translate3D(18.6%, 210%, calc(var(--itemZ) * var(--cameraSpeed) * 40 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(41) { + transform: translate3D(2%, 290%, calc(var(--itemZ) * var(--cameraSpeed) * 41 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(42) { + transform: translate3D(16.6%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 42 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(43) { + transform: translate3D(4.9%, 81%, calc(var(--itemZ) * var(--cameraSpeed) * 43 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(44) { + transform: translate3D(6.3%, 158%, calc(var(--itemZ) * var(--cameraSpeed) * 44 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(45) { + transform: translate3D(6.8%, 187%, calc(var(--itemZ) * var(--cameraSpeed) * 45 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(46) { + transform: translate3D(17.7%, 135%, calc(var(--itemZ) * var(--cameraSpeed) * 46 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(47) { + transform: translate3D(12.9%, 223%, calc(var(--itemZ) * var(--cameraSpeed) * 47 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(48) { + transform: translate3D(15.4%, 35%, calc(var(--itemZ) * var(--cameraSpeed) * 48 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(49) { + transform: translate3D(11.1%, 11%, calc(var(--itemZ) * var(--cameraSpeed) * 49 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(50) { + transform: translate3D(17%, 200%, calc(var(--itemZ) * var(--cameraSpeed) * 50 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(51) { + transform: translate3D(19.1%, 3%, calc(var(--itemZ) * var(--cameraSpeed) * 51 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(52) { + transform: translate3D(18.7%, 239%, calc(var(--itemZ) * var(--cameraSpeed) * 52 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(53) { + transform: translate3D(3.7%, 32%, calc(var(--itemZ) * var(--cameraSpeed) * 53 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(54) { + transform: translate3D(19.1%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 54 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(55) { + transform: translate3D(2.1%, 233%, calc(var(--itemZ) * var(--cameraSpeed) * 55 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(56) { + transform: translate3D(3.2%, 29%, calc(var(--itemZ) * var(--cameraSpeed) * 56 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(57) { + transform: translate3D(3.2%, 225%, calc(var(--itemZ) * var(--cameraSpeed) * 57 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(58) { + transform: translate3D(7.1%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 58 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(59) { + transform: translate3D(14.2%, 263%, calc(var(--itemZ) * var(--cameraSpeed) * 59 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(60) { + transform: translate3D(18.2%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 60 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(61) { + transform: translate3D(11.5%, 108%, calc(var(--itemZ) * var(--cameraSpeed) * 61 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(62) { + transform: translate3D(1.6%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 62 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(63) { + transform: translate3D(15.5%, 223%, calc(var(--itemZ) * var(--cameraSpeed) * 63 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(64) { + transform: translate3D(16.3%, 81%, calc(var(--itemZ) * var(--cameraSpeed) * 64 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(65) { + transform: translate3D(19.7%, 294%, calc(var(--itemZ) * var(--cameraSpeed) * 65 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(66) { + transform: translate3D(12.2%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 66 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(67) { + transform: translate3D(11.9%, 21%, calc(var(--itemZ) * var(--cameraSpeed) * 67 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(68) { + transform: translate3D(15.3%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 68 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(69) { + transform: translate3D(13%, 75%, calc(var(--itemZ) * var(--cameraSpeed) * 69 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(70) { + transform: translate3D(12.2%, 87%, calc(var(--itemZ) * var(--cameraSpeed) * 70 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(71) { + transform: translate3D(16.2%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 71 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(72) { + transform: translate3D(10.7%, 179%, calc(var(--itemZ) * var(--cameraSpeed) * 72 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(73) { + transform: translate3D(3.2%, 243%, calc(var(--itemZ) * var(--cameraSpeed) * 73 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(74) { + transform: translate3D(1.9%, 175%, calc(var(--itemZ) * var(--cameraSpeed) * 74 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(75) { + transform: translate3D(7.1%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 75 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(76) { + transform: translate3D(17.5%, 123%, calc(var(--itemZ) * var(--cameraSpeed) * 76 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(77) { + transform: translate3D(9.6%, 146%, calc(var(--itemZ) * var(--cameraSpeed) * 77 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(78) { + transform: translate3D(5%, 286%, calc(var(--itemZ) * var(--cameraSpeed) * 78 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(79) { + transform: translate3D(18.4%, 207%, calc(var(--itemZ) * var(--cameraSpeed) * 79 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(80) { + transform: translate3D(11.7%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 80 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(81) { + transform: translate3D(9.7%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 81 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(82) { + transform: translate3D(17.7%, 37%, calc(var(--itemZ) * var(--cameraSpeed) * 82 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(83) { + transform: translate3D(17.5%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 83 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(84) { + transform: translate3D(15.7%, 161%, calc(var(--itemZ) * var(--cameraSpeed) * 84 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(85) { + transform: translate3D(18.1%, 104%, calc(var(--itemZ) * var(--cameraSpeed) * 85 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(86) { + transform: translate3D(17.8%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 86 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(87) { + transform: translate3D(18.1%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 87 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(88) { + transform: translate3D(9.1%, 160%, calc(var(--itemZ) * var(--cameraSpeed) * 88 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(89) { + transform: translate3D(4.6%, 217%, calc(var(--itemZ) * var(--cameraSpeed) * 89 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(90) { + transform: translate3D(19.5%, 218%, calc(var(--itemZ) * var(--cameraSpeed) * 90 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(91) { + transform: translate3D(16.8%, 113%, calc(var(--itemZ) * var(--cameraSpeed) * 91 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(92) { + transform: translate3D(6.7%, 34%, calc(var(--itemZ) * var(--cameraSpeed) * 92 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(93) { + transform: translate3D(4.3%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 93 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(94) { + transform: translate3D(6.9%, 222%, calc(var(--itemZ) * var(--cameraSpeed) * 94 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(95) { + transform: translate3D(3.3%, 79%, calc(var(--itemZ) * var(--cameraSpeed) * 95 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(96) { + transform: translate3D(6.6%, 175%, calc(var(--itemZ) * var(--cameraSpeed) * 96 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(97) { + transform: translate3D(1%, 22%, calc(var(--itemZ) * var(--cameraSpeed) * 97 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(98) { + transform: translate3D(2.6%, 39%, calc(var(--itemZ) * var(--cameraSpeed) * 98 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(99) { + transform: translate3D(8.8%, 147%, calc(var(--itemZ) * var(--cameraSpeed) * 99 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(100) { + transform: translate3D(10.8%, 46%, calc(var(--itemZ) * var(--cameraSpeed) * 100 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(101) { + transform: translate3D(15.9%, 115%, calc(var(--itemZ) * var(--cameraSpeed) * 101 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(102) { + transform: translate3D(17.5%, 46%, calc(var(--itemZ) * var(--cameraSpeed) * 102 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(103) { + transform: translate3D(0.8%, 152%, calc(var(--itemZ) * var(--cameraSpeed) * 103 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(104) { + transform: translate3D(8.1%, 33%, calc(var(--itemZ) * var(--cameraSpeed) * 104 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(105) { + transform: translate3D(18.8%, 69%, calc(var(--itemZ) * var(--cameraSpeed) * 105 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(106) { + transform: translate3D(7%, 138%, calc(var(--itemZ) * var(--cameraSpeed) * 106 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(107) { + transform: translate3D(7.5%, 46%, calc(var(--itemZ) * var(--cameraSpeed) * 107 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(108) { + transform: translate3D(19.7%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 108 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(109) { + transform: translate3D(2.9%, 242%, calc(var(--itemZ) * var(--cameraSpeed) * 109 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(110) { + transform: translate3D(2.8%, 192%, calc(var(--itemZ) * var(--cameraSpeed) * 110 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(111) { + transform: translate3D(7.2%, 10%, calc(var(--itemZ) * var(--cameraSpeed) * 111 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(112) { + transform: translate3D(6.3%, 52%, calc(var(--itemZ) * var(--cameraSpeed) * 112 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(113) { + transform: translate3D(6.4%, 230%, calc(var(--itemZ) * var(--cameraSpeed) * 113 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(114) { + transform: translate3D(5.8%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 114 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(115) { + transform: translate3D(16.1%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 115 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(116) { + transform: translate3D(18.3%, 31%, calc(var(--itemZ) * var(--cameraSpeed) * 116 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(117) { + transform: translate3D(8%, 206%, calc(var(--itemZ) * var(--cameraSpeed) * 117 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(118) { + transform: translate3D(7.5%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 118 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(119) { + transform: translate3D(12%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 119 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(120) { + transform: translate3D(7.6%, 176%, calc(var(--itemZ) * var(--cameraSpeed) * 120 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(121) { + transform: translate3D(12.6%, 287%, calc(var(--itemZ) * var(--cameraSpeed) * 121 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(122) { + transform: translate3D(11.5%, 153%, calc(var(--itemZ) * var(--cameraSpeed) * 122 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(123) { + transform: translate3D(8%, 58%, calc(var(--itemZ) * var(--cameraSpeed) * 123 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(124) { + transform: translate3D(10.9%, 149%, calc(var(--itemZ) * var(--cameraSpeed) * 124 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(125) { + transform: translate3D(1.1%, 281%, calc(var(--itemZ) * var(--cameraSpeed) * 125 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(126) { + transform: translate3D(18.4%, 104%, calc(var(--itemZ) * var(--cameraSpeed) * 126 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(127) { + transform: translate3D(4.8%, 116%, calc(var(--itemZ) * var(--cameraSpeed) * 127 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(128) { + transform: translate3D(4.3%, 109%, calc(var(--itemZ) * var(--cameraSpeed) * 128 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(129) { + transform: translate3D(15.2%, 40%, calc(var(--itemZ) * var(--cameraSpeed) * 129 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(130) { + transform: translate3D(1.8%, 90%, calc(var(--itemZ) * var(--cameraSpeed) * 130 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(131) { + transform: translate3D(6.3%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 131 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(132) { + transform: translate3D(7.9%, 210%, calc(var(--itemZ) * var(--cameraSpeed) * 132 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(133) { + transform: translate3D(4.7%, 162%, calc(var(--itemZ) * var(--cameraSpeed) * 133 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(134) { + transform: translate3D(11.5%, 180%, calc(var(--itemZ) * var(--cameraSpeed) * 134 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(135) { + transform: translate3D(13.3%, 255%, calc(var(--itemZ) * var(--cameraSpeed) * 135 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(136) { + transform: translate3D(5.6%, 227%, calc(var(--itemZ) * var(--cameraSpeed) * 136 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(137) { + transform: translate3D(13.9%, 283%, calc(var(--itemZ) * var(--cameraSpeed) * 137 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(138) { + transform: translate3D(2.8%, 72%, calc(var(--itemZ) * var(--cameraSpeed) * 138 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(139) { + transform: translate3D(12.2%, 168%, calc(var(--itemZ) * var(--cameraSpeed) * 139 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(140) { + transform: translate3D(19.9%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 140 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(141) { + transform: translate3D(1.3%, 100%, calc(var(--itemZ) * var(--cameraSpeed) * 141 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(142) { + transform: translate3D(7.3%, 210%, calc(var(--itemZ) * var(--cameraSpeed) * 142 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(143) { + transform: translate3D(6.1%, 278%, calc(var(--itemZ) * var(--cameraSpeed) * 143 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(144) { + transform: translate3D(19%, 104%, calc(var(--itemZ) * var(--cameraSpeed) * 144 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(145) { + transform: translate3D(2.8%, 32%, calc(var(--itemZ) * var(--cameraSpeed) * 145 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(146) { + transform: translate3D(17.6%, 217%, calc(var(--itemZ) * var(--cameraSpeed) * 146 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(147) { + transform: translate3D(8.6%, 85%, calc(var(--itemZ) * var(--cameraSpeed) * 147 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(148) { + transform: translate3D(13.7%, 156%, calc(var(--itemZ) * var(--cameraSpeed) * 148 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(149) { + transform: translate3D(19.4%, 113%, calc(var(--itemZ) * var(--cameraSpeed) * 149 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(150) { + transform: translate3D(14.1%, 192%, calc(var(--itemZ) * var(--cameraSpeed) * 150 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(151) { + transform: translate3D(11%, 128%, calc(var(--itemZ) * var(--cameraSpeed) * 151 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(152) { + transform: translate3D(8.5%, 17%, calc(var(--itemZ) * var(--cameraSpeed) * 152 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(153) { + transform: translate3D(16.9%, 282%, calc(var(--itemZ) * var(--cameraSpeed) * 153 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(154) { + transform: translate3D(15.3%, 191%, calc(var(--itemZ) * var(--cameraSpeed) * 154 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(155) { + transform: translate3D(8.9%, 258%, calc(var(--itemZ) * var(--cameraSpeed) * 155 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(156) { + transform: translate3D(16.4%, 27%, calc(var(--itemZ) * var(--cameraSpeed) * 156 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(157) { + transform: translate3D(1.7%, 228%, calc(var(--itemZ) * var(--cameraSpeed) * 157 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(158) { + transform: translate3D(14.3%, 111%, calc(var(--itemZ) * var(--cameraSpeed) * 158 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(159) { + transform: translate3D(1%, 111%, calc(var(--itemZ) * var(--cameraSpeed) * 159 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(160) { + transform: translate3D(19.2%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 160 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(161) { + transform: translate3D(5.3%, 117%, calc(var(--itemZ) * var(--cameraSpeed) * 161 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(162) { + transform: translate3D(16.5%, 233%, calc(var(--itemZ) * var(--cameraSpeed) * 162 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(163) { + transform: translate3D(15.5%, 79%, calc(var(--itemZ) * var(--cameraSpeed) * 163 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(164) { + transform: translate3D(3.1%, 276%, calc(var(--itemZ) * var(--cameraSpeed) * 164 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(165) { + transform: translate3D(14.1%, 147%, calc(var(--itemZ) * var(--cameraSpeed) * 165 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(166) { + transform: translate3D(7.5%, 6%, calc(var(--itemZ) * var(--cameraSpeed) * 166 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(167) { + transform: translate3D(9%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 167 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(168) { + transform: translate3D(18.3%, 285%, calc(var(--itemZ) * var(--cameraSpeed) * 168 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(169) { + transform: translate3D(4.9%, 35%, calc(var(--itemZ) * var(--cameraSpeed) * 169 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(170) { + transform: translate3D(12.1%, 79%, calc(var(--itemZ) * var(--cameraSpeed) * 170 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(171) { + transform: translate3D(16.8%, 1%, calc(var(--itemZ) * var(--cameraSpeed) * 171 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(172) { + transform: translate3D(5.7%, 42%, calc(var(--itemZ) * var(--cameraSpeed) * 172 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(173) { + transform: translate3D(8.2%, 134%, calc(var(--itemZ) * var(--cameraSpeed) * 173 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(174) { + transform: translate3D(14.4%, 94%, calc(var(--itemZ) * var(--cameraSpeed) * 174 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(175) { + transform: translate3D(5.3%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 175 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(176) { + transform: translate3D(3.5%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 176 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(177) { + transform: translate3D(3.9%, 132%, calc(var(--itemZ) * var(--cameraSpeed) * 177 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(178) { + transform: translate3D(9.1%, 236%, calc(var(--itemZ) * var(--cameraSpeed) * 178 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(179) { + transform: translate3D(14.4%, 9%, calc(var(--itemZ) * var(--cameraSpeed) * 179 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(180) { + transform: translate3D(2.9%, 92%, calc(var(--itemZ) * var(--cameraSpeed) * 180 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(181) { + transform: translate3D(8.5%, 16%, calc(var(--itemZ) * var(--cameraSpeed) * 181 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(182) { + transform: translate3D(1.2%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 182 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(183) { + transform: translate3D(12.5%, 285%, calc(var(--itemZ) * var(--cameraSpeed) * 183 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(184) { + transform: translate3D(9%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 184 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(185) { + transform: translate3D(12%, 299%, calc(var(--itemZ) * var(--cameraSpeed) * 185 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(186) { + transform: translate3D(6.6%, 138%, calc(var(--itemZ) * var(--cameraSpeed) * 186 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(187) { + transform: translate3D(11.9%, 191%, calc(var(--itemZ) * var(--cameraSpeed) * 187 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(188) { + transform: translate3D(7.2%, 109%, calc(var(--itemZ) * var(--cameraSpeed) * 188 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(189) { + transform: translate3D(0.6%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 189 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(190) { + transform: translate3D(6.2%, 299%, calc(var(--itemZ) * var(--cameraSpeed) * 190 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(191) { + transform: translate3D(3.5%, 106%, calc(var(--itemZ) * var(--cameraSpeed) * 191 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(192) { + transform: translate3D(2.9%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 192 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(193) { + transform: translate3D(16.7%, 146%, calc(var(--itemZ) * var(--cameraSpeed) * 193 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(194) { + transform: translate3D(3.6%, 41%, calc(var(--itemZ) * var(--cameraSpeed) * 194 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(195) { + transform: translate3D(15.7%, 10%, calc(var(--itemZ) * var(--cameraSpeed) * 195 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(196) { + transform: translate3D(12.2%, 67%, calc(var(--itemZ) * var(--cameraSpeed) * 196 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(197) { + transform: translate3D(15.6%, 189%, calc(var(--itemZ) * var(--cameraSpeed) * 197 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(198) { + transform: translate3D(7.9%, 34%, calc(var(--itemZ) * var(--cameraSpeed) * 198 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(199) { + transform: translate3D(10.5%, 275%, calc(var(--itemZ) * var(--cameraSpeed) * 199 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(200) { + transform: translate3D(13.3%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 200 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(201) { + transform: translate3D(13.9%, 45%, calc(var(--itemZ) * var(--cameraSpeed) * 201 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(202) { + transform: translate3D(14.7%, 32%, calc(var(--itemZ) * var(--cameraSpeed) * 202 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(203) { + transform: translate3D(8.9%, 203%, calc(var(--itemZ) * var(--cameraSpeed) * 203 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(204) { + transform: translate3D(4.6%, 122%, calc(var(--itemZ) * var(--cameraSpeed) * 204 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(205) { + transform: translate3D(4%, 153%, calc(var(--itemZ) * var(--cameraSpeed) * 205 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(206) { + transform: translate3D(14.8%, 246%, calc(var(--itemZ) * var(--cameraSpeed) * 206 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(207) { + transform: translate3D(14.4%, 140%, calc(var(--itemZ) * var(--cameraSpeed) * 207 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(208) { + transform: translate3D(8%, 271%, calc(var(--itemZ) * var(--cameraSpeed) * 208 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(209) { + transform: translate3D(1.9%, 70%, calc(var(--itemZ) * var(--cameraSpeed) * 209 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(210) { + transform: translate3D(18.7%, 237%, calc(var(--itemZ) * var(--cameraSpeed) * 210 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(211) { + transform: translate3D(10.2%, 242%, calc(var(--itemZ) * var(--cameraSpeed) * 211 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(212) { + transform: translate3D(1.5%, 295%, calc(var(--itemZ) * var(--cameraSpeed) * 212 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(213) { + transform: translate3D(1.1%, 280%, calc(var(--itemZ) * var(--cameraSpeed) * 213 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(214) { + transform: translate3D(6.1%, 11%, calc(var(--itemZ) * var(--cameraSpeed) * 214 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(215) { + transform: translate3D(7.9%, 106%, calc(var(--itemZ) * var(--cameraSpeed) * 215 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(216) { + transform: translate3D(5.4%, 270%, calc(var(--itemZ) * var(--cameraSpeed) * 216 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(217) { + transform: translate3D(5.5%, 263%, calc(var(--itemZ) * var(--cameraSpeed) * 217 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(218) { + transform: translate3D(16.7%, 134%, calc(var(--itemZ) * var(--cameraSpeed) * 218 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(219) { + transform: translate3D(1.1%, 137%, calc(var(--itemZ) * var(--cameraSpeed) * 219 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(220) { + transform: translate3D(16.1%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 220 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(221) { + transform: translate3D(7.9%, 72%, calc(var(--itemZ) * var(--cameraSpeed) * 221 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(222) { + transform: translate3D(7.3%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 222 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(223) { + transform: translate3D(9.7%, 272%, calc(var(--itemZ) * var(--cameraSpeed) * 223 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(224) { + transform: translate3D(8.9%, 52%, calc(var(--itemZ) * var(--cameraSpeed) * 224 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(225) { + transform: translate3D(1.6%, 211%, calc(var(--itemZ) * var(--cameraSpeed) * 225 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(226) { + transform: translate3D(11.6%, 133%, calc(var(--itemZ) * var(--cameraSpeed) * 226 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(227) { + transform: translate3D(19.6%, 216%, calc(var(--itemZ) * var(--cameraSpeed) * 227 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(228) { + transform: translate3D(15.2%, 173%, calc(var(--itemZ) * var(--cameraSpeed) * 228 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(229) { + transform: translate3D(7.9%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 229 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(230) { + transform: translate3D(15%, 69%, calc(var(--itemZ) * var(--cameraSpeed) * 230 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(231) { + transform: translate3D(8%, 145%, calc(var(--itemZ) * var(--cameraSpeed) * 231 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(232) { + transform: translate3D(16.8%, 66%, calc(var(--itemZ) * var(--cameraSpeed) * 232 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(233) { + transform: translate3D(4.3%, 189%, calc(var(--itemZ) * var(--cameraSpeed) * 233 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(234) { + transform: translate3D(13.7%, 56%, calc(var(--itemZ) * var(--cameraSpeed) * 234 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(235) { + transform: translate3D(3.2%, 132%, calc(var(--itemZ) * var(--cameraSpeed) * 235 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(236) { + transform: translate3D(16.4%, 165%, calc(var(--itemZ) * var(--cameraSpeed) * 236 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(237) { + transform: translate3D(9.3%, 164%, calc(var(--itemZ) * var(--cameraSpeed) * 237 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(238) { + transform: translate3D(8.9%, 161%, calc(var(--itemZ) * var(--cameraSpeed) * 238 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(239) { + transform: translate3D(10.7%, 118%, calc(var(--itemZ) * var(--cameraSpeed) * 239 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(240) { + transform: translate3D(14%, 21%, calc(var(--itemZ) * var(--cameraSpeed) * 240 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(241) { + transform: translate3D(11.2%, 126%, calc(var(--itemZ) * var(--cameraSpeed) * 241 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(242) { + transform: translate3D(19.6%, 63%, calc(var(--itemZ) * var(--cameraSpeed) * 242 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(243) { + transform: translate3D(14.3%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 243 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(244) { + transform: translate3D(12.4%, 72%, calc(var(--itemZ) * var(--cameraSpeed) * 244 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(245) { + transform: translate3D(11.1%, 93%, calc(var(--itemZ) * var(--cameraSpeed) * 245 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(246) { + transform: translate3D(16.2%, 157%, calc(var(--itemZ) * var(--cameraSpeed) * 246 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(247) { + transform: translate3D(18.3%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 247 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(248) { + transform: translate3D(13.7%, 107%, calc(var(--itemZ) * var(--cameraSpeed) * 248 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(249) { + transform: translate3D(0.3%, 243%, calc(var(--itemZ) * var(--cameraSpeed) * 249 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(250) { + transform: translate3D(4.1%, 265%, calc(var(--itemZ) * var(--cameraSpeed) * 250 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(251) { + transform: translate3D(14.8%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 251 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(252) { + transform: translate3D(0.9%, 7%, calc(var(--itemZ) * var(--cameraSpeed) * 252 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(253) { + transform: translate3D(8.2%, 96%, calc(var(--itemZ) * var(--cameraSpeed) * 253 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(254) { + transform: translate3D(15.2%, 49%, calc(var(--itemZ) * var(--cameraSpeed) * 254 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(255) { + transform: translate3D(13.3%, 67%, calc(var(--itemZ) * var(--cameraSpeed) * 255 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(256) { + transform: translate3D(10.2%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 256 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(257) { + transform: translate3D(12.3%, 118%, calc(var(--itemZ) * var(--cameraSpeed) * 257 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(258) { + transform: translate3D(17%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 258 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(259) { + transform: translate3D(6.3%, 51%, calc(var(--itemZ) * var(--cameraSpeed) * 259 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(260) { + transform: translate3D(16.4%, 77%, calc(var(--itemZ) * var(--cameraSpeed) * 260 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(261) { + transform: translate3D(5.1%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 261 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(262) { + transform: translate3D(14.1%, 114%, calc(var(--itemZ) * var(--cameraSpeed) * 262 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(263) { + transform: translate3D(15%, 160%, calc(var(--itemZ) * var(--cameraSpeed) * 263 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(264) { + transform: translate3D(6.8%, 180%, calc(var(--itemZ) * var(--cameraSpeed) * 264 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(265) { + transform: translate3D(14.2%, 162%, calc(var(--itemZ) * var(--cameraSpeed) * 265 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(266) { + transform: translate3D(3.4%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 266 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(267) { + transform: translate3D(7.6%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 267 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(268) { + transform: translate3D(14.9%, 243%, calc(var(--itemZ) * var(--cameraSpeed) * 268 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(269) { + transform: translate3D(4%, 220%, calc(var(--itemZ) * var(--cameraSpeed) * 269 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(270) { + transform: translate3D(9.7%, 202%, calc(var(--itemZ) * var(--cameraSpeed) * 270 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(271) { + transform: translate3D(8.3%, 143%, calc(var(--itemZ) * var(--cameraSpeed) * 271 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(272) { + transform: translate3D(19.9%, 168%, calc(var(--itemZ) * var(--cameraSpeed) * 272 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(273) { + transform: translate3D(6.2%, 38%, calc(var(--itemZ) * var(--cameraSpeed) * 273 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(274) { + transform: translate3D(0.5%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 274 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(275) { + transform: translate3D(13.4%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 275 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(276) { + transform: translate3D(11.2%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 276 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(277) { + transform: translate3D(5.5%, 165%, calc(var(--itemZ) * var(--cameraSpeed) * 277 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(278) { + transform: translate3D(7.3%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 278 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(279) { + transform: translate3D(1.8%, 18%, calc(var(--itemZ) * var(--cameraSpeed) * 279 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(280) { + transform: translate3D(2.9%, 258%, calc(var(--itemZ) * var(--cameraSpeed) * 280 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(281) { + transform: translate3D(11.9%, 204%, calc(var(--itemZ) * var(--cameraSpeed) * 281 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(282) { + transform: translate3D(19.5%, 42%, calc(var(--itemZ) * var(--cameraSpeed) * 282 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(283) { + transform: translate3D(16.9%, 213%, calc(var(--itemZ) * var(--cameraSpeed) * 283 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(284) { + transform: translate3D(7.2%, 197%, calc(var(--itemZ) * var(--cameraSpeed) * 284 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(285) { + transform: translate3D(10.1%, 288%, calc(var(--itemZ) * var(--cameraSpeed) * 285 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(286) { + transform: translate3D(14.3%, 178%, calc(var(--itemZ) * var(--cameraSpeed) * 286 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(287) { + transform: translate3D(14.7%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 287 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(288) { + transform: translate3D(9.3%, 257%, calc(var(--itemZ) * var(--cameraSpeed) * 288 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(289) { + transform: translate3D(17.8%, 54%, calc(var(--itemZ) * var(--cameraSpeed) * 289 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(290) { + transform: translate3D(7.4%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 290 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(291) { + transform: translate3D(5.6%, 37%, calc(var(--itemZ) * var(--cameraSpeed) * 291 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(292) { + transform: translate3D(5.3%, 250%, calc(var(--itemZ) * var(--cameraSpeed) * 292 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(293) { + transform: translate3D(15.5%, 139%, calc(var(--itemZ) * var(--cameraSpeed) * 293 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(294) { + transform: translate3D(0.1%, 22%, calc(var(--itemZ) * var(--cameraSpeed) * 294 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(295) { + transform: translate3D(10.2%, 31%, calc(var(--itemZ) * var(--cameraSpeed) * 295 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(296) { + transform: translate3D(17.8%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 296 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(297) { + transform: translate3D(19.7%, 40%, calc(var(--itemZ) * var(--cameraSpeed) * 297 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(298) { + transform: translate3D(4.3%, 19%, calc(var(--itemZ) * var(--cameraSpeed) * 298 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(299) { + transform: translate3D(9%, 264%, calc(var(--itemZ) * var(--cameraSpeed) * 299 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(300) { + transform: translate3D(17.6%, 194%, calc(var(--itemZ) * var(--cameraSpeed) * 300 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(301) { + transform: translate3D(19.4%, 256%, calc(var(--itemZ) * var(--cameraSpeed) * 301 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(302) { + transform: translate3D(17.7%, 27%, calc(var(--itemZ) * var(--cameraSpeed) * 302 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(303) { + transform: translate3D(4.2%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 303 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(304) { + transform: translate3D(12%, 189%, calc(var(--itemZ) * var(--cameraSpeed) * 304 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(305) { + transform: translate3D(3.3%, 145%, calc(var(--itemZ) * var(--cameraSpeed) * 305 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(306) { + transform: translate3D(17.1%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 306 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(307) { + transform: translate3D(17.6%, 40%, calc(var(--itemZ) * var(--cameraSpeed) * 307 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(308) { + transform: translate3D(14.3%, 9%, calc(var(--itemZ) * var(--cameraSpeed) * 308 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(309) { + transform: translate3D(19.1%, 69%, calc(var(--itemZ) * var(--cameraSpeed) * 309 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(310) { + transform: translate3D(15.6%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 310 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(311) { + transform: translate3D(8.4%, 241%, calc(var(--itemZ) * var(--cameraSpeed) * 311 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(312) { + transform: translate3D(11%, 131%, calc(var(--itemZ) * var(--cameraSpeed) * 312 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(313) { + transform: translate3D(15.5%, 296%, calc(var(--itemZ) * var(--cameraSpeed) * 313 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(314) { + transform: translate3D(15.1%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 314 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(315) { + transform: translate3D(8.7%, 283%, calc(var(--itemZ) * var(--cameraSpeed) * 315 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(316) { + transform: translate3D(3.3%, 57%, calc(var(--itemZ) * var(--cameraSpeed) * 316 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(317) { + transform: translate3D(16.7%, 96%, calc(var(--itemZ) * var(--cameraSpeed) * 317 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(318) { + transform: translate3D(14.6%, 147%, calc(var(--itemZ) * var(--cameraSpeed) * 318 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(319) { + transform: translate3D(14.3%, 279%, calc(var(--itemZ) * var(--cameraSpeed) * 319 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(320) { + transform: translate3D(10.7%, 7%, calc(var(--itemZ) * var(--cameraSpeed) * 320 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(321) { + transform: translate3D(7.4%, 3%, calc(var(--itemZ) * var(--cameraSpeed) * 321 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(322) { + transform: translate3D(10%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 322 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(323) { + transform: translate3D(12.5%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 323 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(324) { + transform: translate3D(12.4%, 79%, calc(var(--itemZ) * var(--cameraSpeed) * 324 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(325) { + transform: translate3D(2.6%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 325 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(326) { + transform: translate3D(4.8%, 76%, calc(var(--itemZ) * var(--cameraSpeed) * 326 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(327) { + transform: translate3D(17%, 124%, calc(var(--itemZ) * var(--cameraSpeed) * 327 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(328) { + transform: translate3D(4.5%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 328 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(329) { + transform: translate3D(11.9%, 141%, calc(var(--itemZ) * var(--cameraSpeed) * 329 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(330) { + transform: translate3D(0.5%, 150%, calc(var(--itemZ) * var(--cameraSpeed) * 330 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(331) { + transform: translate3D(5.4%, 128%, calc(var(--itemZ) * var(--cameraSpeed) * 331 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(332) { + transform: translate3D(2.4%, 4%, calc(var(--itemZ) * var(--cameraSpeed) * 332 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(333) { + transform: translate3D(10.2%, 63%, calc(var(--itemZ) * var(--cameraSpeed) * 333 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(334) { + transform: translate3D(15.9%, 22%, calc(var(--itemZ) * var(--cameraSpeed) * 334 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(335) { + transform: translate3D(19.8%, 167%, calc(var(--itemZ) * var(--cameraSpeed) * 335 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(336) { + transform: translate3D(7.5%, 256%, calc(var(--itemZ) * var(--cameraSpeed) * 336 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(337) { + transform: translate3D(3.2%, 148%, calc(var(--itemZ) * var(--cameraSpeed) * 337 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(338) { + transform: translate3D(13.6%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 338 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(339) { + transform: translate3D(5.3%, 82%, calc(var(--itemZ) * var(--cameraSpeed) * 339 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(340) { + transform: translate3D(3.1%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 340 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(341) { + transform: translate3D(2%, 271%, calc(var(--itemZ) * var(--cameraSpeed) * 341 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(342) { + transform: translate3D(11.7%, 66%, calc(var(--itemZ) * var(--cameraSpeed) * 342 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(343) { + transform: translate3D(7.9%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 343 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(344) { + transform: translate3D(11.5%, 91%, calc(var(--itemZ) * var(--cameraSpeed) * 344 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(345) { + transform: translate3D(1.7%, 292%, calc(var(--itemZ) * var(--cameraSpeed) * 345 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(346) { + transform: translate3D(14.6%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 346 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(347) { + transform: translate3D(6.8%, 8%, calc(var(--itemZ) * var(--cameraSpeed) * 347 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(348) { + transform: translate3D(14.3%, 93%, calc(var(--itemZ) * var(--cameraSpeed) * 348 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(349) { + transform: translate3D(18%, 161%, calc(var(--itemZ) * var(--cameraSpeed) * 349 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(350) { + transform: translate3D(11.7%, 221%, calc(var(--itemZ) * var(--cameraSpeed) * 350 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(351) { + transform: translate3D(16.3%, 264%, calc(var(--itemZ) * var(--cameraSpeed) * 351 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(352) { + transform: translate3D(0.2%, 143%, calc(var(--itemZ) * var(--cameraSpeed) * 352 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(353) { + transform: translate3D(18.6%, 49%, calc(var(--itemZ) * var(--cameraSpeed) * 353 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(354) { + transform: translate3D(4.6%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 354 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(355) { + transform: translate3D(12%, 33%, calc(var(--itemZ) * var(--cameraSpeed) * 355 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(356) { + transform: translate3D(10.3%, 222%, calc(var(--itemZ) * var(--cameraSpeed) * 356 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(357) { + transform: translate3D(5%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 357 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(358) { + transform: translate3D(16.9%, 281%, calc(var(--itemZ) * var(--cameraSpeed) * 358 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(359) { + transform: translate3D(13.3%, 294%, calc(var(--itemZ) * var(--cameraSpeed) * 359 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(360) { + transform: translate3D(19.2%, 60%, calc(var(--itemZ) * var(--cameraSpeed) * 360 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(361) { + transform: translate3D(9.6%, 202%, calc(var(--itemZ) * var(--cameraSpeed) * 361 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(362) { + transform: translate3D(0.4%, 182%, calc(var(--itemZ) * var(--cameraSpeed) * 362 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(363) { + transform: translate3D(13.8%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 363 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(364) { + transform: translate3D(2.5%, 64%, calc(var(--itemZ) * var(--cameraSpeed) * 364 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(365) { + transform: translate3D(17.2%, 281%, calc(var(--itemZ) * var(--cameraSpeed) * 365 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(366) { + transform: translate3D(16.2%, 116%, calc(var(--itemZ) * var(--cameraSpeed) * 366 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(367) { + transform: translate3D(11.9%, 246%, calc(var(--itemZ) * var(--cameraSpeed) * 367 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(368) { + transform: translate3D(14.3%, 79%, calc(var(--itemZ) * var(--cameraSpeed) * 368 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(369) { + transform: translate3D(1.1%, 206%, calc(var(--itemZ) * var(--cameraSpeed) * 369 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(370) { + transform: translate3D(19.7%, 118%, calc(var(--itemZ) * var(--cameraSpeed) * 370 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(371) { + transform: translate3D(5.4%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 371 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(372) { + transform: translate3D(3%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 372 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(373) { + transform: translate3D(4.5%, 162%, calc(var(--itemZ) * var(--cameraSpeed) * 373 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(374) { + transform: translate3D(6%, 227%, calc(var(--itemZ) * var(--cameraSpeed) * 374 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(375) { + transform: translate3D(18.5%, 133%, calc(var(--itemZ) * var(--cameraSpeed) * 375 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(376) { + transform: translate3D(3.7%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 376 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(377) { + transform: translate3D(11.3%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 377 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(378) { + transform: translate3D(4.4%, 138%, calc(var(--itemZ) * var(--cameraSpeed) * 378 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(379) { + transform: translate3D(13.3%, 205%, calc(var(--itemZ) * var(--cameraSpeed) * 379 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(380) { + transform: translate3D(18%, 183%, calc(var(--itemZ) * var(--cameraSpeed) * 380 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(381) { + transform: translate3D(18.8%, 97%, calc(var(--itemZ) * var(--cameraSpeed) * 381 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(382) { + transform: translate3D(9.1%, 137%, calc(var(--itemZ) * var(--cameraSpeed) * 382 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(383) { + transform: translate3D(7.9%, 255%, calc(var(--itemZ) * var(--cameraSpeed) * 383 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(384) { + transform: translate3D(3.6%, 8%, calc(var(--itemZ) * var(--cameraSpeed) * 384 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(385) { + transform: translate3D(9.3%, 170%, calc(var(--itemZ) * var(--cameraSpeed) * 385 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(386) { + transform: translate3D(9.7%, 197%, calc(var(--itemZ) * var(--cameraSpeed) * 386 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(387) { + transform: translate3D(17.6%, 41%, calc(var(--itemZ) * var(--cameraSpeed) * 387 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(388) { + transform: translate3D(16.6%, 99%, calc(var(--itemZ) * var(--cameraSpeed) * 388 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(389) { + transform: translate3D(9%, 105%, calc(var(--itemZ) * var(--cameraSpeed) * 389 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(390) { + transform: translate3D(0.5%, 30%, calc(var(--itemZ) * var(--cameraSpeed) * 390 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(391) { + transform: translate3D(1.6%, 93%, calc(var(--itemZ) * var(--cameraSpeed) * 391 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(392) { + transform: translate3D(18.3%, 76%, calc(var(--itemZ) * var(--cameraSpeed) * 392 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(393) { + transform: translate3D(9.1%, 23%, calc(var(--itemZ) * var(--cameraSpeed) * 393 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(394) { + transform: translate3D(14.5%, 227%, calc(var(--itemZ) * var(--cameraSpeed) * 394 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(395) { + transform: translate3D(10.9%, 74%, calc(var(--itemZ) * var(--cameraSpeed) * 395 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(396) { + transform: translate3D(1.1%, 33%, calc(var(--itemZ) * var(--cameraSpeed) * 396 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(397) { + transform: translate3D(17.9%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 397 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(398) { + transform: translate3D(12.9%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 398 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(399) { + transform: translate3D(10.4%, 45%, calc(var(--itemZ) * var(--cameraSpeed) * 399 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(400) { + transform: translate3D(17.1%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 400 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(401) { + transform: translate3D(8.8%, 142%, calc(var(--itemZ) * var(--cameraSpeed) * 401 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(402) { + transform: translate3D(12.5%, 163%, calc(var(--itemZ) * var(--cameraSpeed) * 402 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(403) { + transform: translate3D(13.7%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 403 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(404) { + transform: translate3D(12.2%, 224%, calc(var(--itemZ) * var(--cameraSpeed) * 404 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(405) { + transform: translate3D(4%, 88%, calc(var(--itemZ) * var(--cameraSpeed) * 405 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(406) { + transform: translate3D(0.7%, 112%, calc(var(--itemZ) * var(--cameraSpeed) * 406 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(407) { + transform: translate3D(9%, 95%, calc(var(--itemZ) * var(--cameraSpeed) * 407 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(408) { + transform: translate3D(3.6%, 291%, calc(var(--itemZ) * var(--cameraSpeed) * 408 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(409) { + transform: translate3D(11.4%, 111%, calc(var(--itemZ) * var(--cameraSpeed) * 409 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(410) { + transform: translate3D(7.6%, 183%, calc(var(--itemZ) * var(--cameraSpeed) * 410 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(411) { + transform: translate3D(11.8%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 411 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(412) { + transform: translate3D(12.9%, 28%, calc(var(--itemZ) * var(--cameraSpeed) * 412 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(413) { + transform: translate3D(2%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 413 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(414) { + transform: translate3D(15.7%, 113%, calc(var(--itemZ) * var(--cameraSpeed) * 414 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(415) { + transform: translate3D(13%, 271%, calc(var(--itemZ) * var(--cameraSpeed) * 415 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(416) { + transform: translate3D(17%, 80%, calc(var(--itemZ) * var(--cameraSpeed) * 416 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(417) { + transform: translate3D(17.4%, 3%, calc(var(--itemZ) * var(--cameraSpeed) * 417 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(418) { + transform: translate3D(5.4%, 180%, calc(var(--itemZ) * var(--cameraSpeed) * 418 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(419) { + transform: translate3D(1.3%, 27%, calc(var(--itemZ) * var(--cameraSpeed) * 419 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(420) { + transform: translate3D(7%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 420 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(421) { + transform: translate3D(7.7%, 132%, calc(var(--itemZ) * var(--cameraSpeed) * 421 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(422) { + transform: translate3D(14.4%, 241%, calc(var(--itemZ) * var(--cameraSpeed) * 422 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(423) { + transform: translate3D(16.1%, 214%, calc(var(--itemZ) * var(--cameraSpeed) * 423 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(424) { + transform: translate3D(17.8%, 137%, calc(var(--itemZ) * var(--cameraSpeed) * 424 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(425) { + transform: translate3D(3.8%, 216%, calc(var(--itemZ) * var(--cameraSpeed) * 425 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(426) { + transform: translate3D(7.4%, 87%, calc(var(--itemZ) * var(--cameraSpeed) * 426 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(427) { + transform: translate3D(19.3%, 33%, calc(var(--itemZ) * var(--cameraSpeed) * 427 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(428) { + transform: translate3D(6.1%, 10%, calc(var(--itemZ) * var(--cameraSpeed) * 428 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(429) { + transform: translate3D(9.2%, 168%, calc(var(--itemZ) * var(--cameraSpeed) * 429 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(430) { + transform: translate3D(3.7%, 220%, calc(var(--itemZ) * var(--cameraSpeed) * 430 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(431) { + transform: translate3D(15%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 431 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(432) { + transform: translate3D(0.8%, 130%, calc(var(--itemZ) * var(--cameraSpeed) * 432 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(433) { + transform: translate3D(15%, 149%, calc(var(--itemZ) * var(--cameraSpeed) * 433 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(434) { + transform: translate3D(1%, 235%, calc(var(--itemZ) * var(--cameraSpeed) * 434 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(435) { + transform: translate3D(8.8%, 257%, calc(var(--itemZ) * var(--cameraSpeed) * 435 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(436) { + transform: translate3D(3.1%, 12%, calc(var(--itemZ) * var(--cameraSpeed) * 436 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(437) { + transform: translate3D(12.1%, 66%, calc(var(--itemZ) * var(--cameraSpeed) * 437 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(438) { + transform: translate3D(15.7%, 271%, calc(var(--itemZ) * var(--cameraSpeed) * 438 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(439) { + transform: translate3D(6.5%, 288%, calc(var(--itemZ) * var(--cameraSpeed) * 439 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(440) { + transform: translate3D(9.1%, 180%, calc(var(--itemZ) * var(--cameraSpeed) * 440 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(441) { + transform: translate3D(5%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 441 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(442) { + transform: translate3D(0.6%, 239%, calc(var(--itemZ) * var(--cameraSpeed) * 442 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(443) { + transform: translate3D(8.6%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 443 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(444) { + transform: translate3D(14%, 297%, calc(var(--itemZ) * var(--cameraSpeed) * 444 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(445) { + transform: translate3D(0.9%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 445 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(446) { + transform: translate3D(11.2%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 446 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(447) { + transform: translate3D(18.3%, 45%, calc(var(--itemZ) * var(--cameraSpeed) * 447 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(448) { + transform: translate3D(14.9%, 275%, calc(var(--itemZ) * var(--cameraSpeed) * 448 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(449) { + transform: translate3D(13%, 11%, calc(var(--itemZ) * var(--cameraSpeed) * 449 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(450) { + transform: translate3D(8.5%, 30%, calc(var(--itemZ) * var(--cameraSpeed) * 450 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(451) { + transform: translate3D(9.7%, 143%, calc(var(--itemZ) * var(--cameraSpeed) * 451 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(452) { + transform: translate3D(4.7%, 165%, calc(var(--itemZ) * var(--cameraSpeed) * 452 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(453) { + transform: translate3D(15.4%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 453 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(454) { + transform: translate3D(17.6%, 287%, calc(var(--itemZ) * var(--cameraSpeed) * 454 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(455) { + transform: translate3D(16%, 91%, calc(var(--itemZ) * var(--cameraSpeed) * 455 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(456) { + transform: translate3D(17.1%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 456 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(457) { + transform: translate3D(1.7%, 184%, calc(var(--itemZ) * var(--cameraSpeed) * 457 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(458) { + transform: translate3D(13.1%, 227%, calc(var(--itemZ) * var(--cameraSpeed) * 458 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(459) { + transform: translate3D(18.1%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 459 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(460) { + transform: translate3D(12.4%, 190%, calc(var(--itemZ) * var(--cameraSpeed) * 460 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(461) { + transform: translate3D(8.7%, 289%, calc(var(--itemZ) * var(--cameraSpeed) * 461 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(462) { + transform: translate3D(12.2%, 293%, calc(var(--itemZ) * var(--cameraSpeed) * 462 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(463) { + transform: translate3D(7%, 162%, calc(var(--itemZ) * var(--cameraSpeed) * 463 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(464) { + transform: translate3D(15.1%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 464 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(465) { + transform: translate3D(19%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 465 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(466) { + transform: translate3D(11.9%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 466 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(467) { + transform: translate3D(16.5%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 467 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(468) { + transform: translate3D(16.8%, 197%, calc(var(--itemZ) * var(--cameraSpeed) * 468 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(469) { + transform: translate3D(17.4%, 263%, calc(var(--itemZ) * var(--cameraSpeed) * 469 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(470) { + transform: translate3D(17.1%, 6%, calc(var(--itemZ) * var(--cameraSpeed) * 470 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(471) { + transform: translate3D(15.2%, 233%, calc(var(--itemZ) * var(--cameraSpeed) * 471 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(472) { + transform: translate3D(8.1%, 57%, calc(var(--itemZ) * var(--cameraSpeed) * 472 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(473) { + transform: translate3D(18%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 473 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(474) { + transform: translate3D(14.2%, 218%, calc(var(--itemZ) * var(--cameraSpeed) * 474 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(475) { + transform: translate3D(0.4%, 60%, calc(var(--itemZ) * var(--cameraSpeed) * 475 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(476) { + transform: translate3D(16.2%, 265%, calc(var(--itemZ) * var(--cameraSpeed) * 476 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(477) { + transform: translate3D(16.9%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 477 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(478) { + transform: translate3D(0.4%, 270%, calc(var(--itemZ) * var(--cameraSpeed) * 478 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(479) { + transform: translate3D(15.3%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 479 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(480) { + transform: translate3D(7.3%, 46%, calc(var(--itemZ) * var(--cameraSpeed) * 480 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(481) { + transform: translate3D(2.8%, 176%, calc(var(--itemZ) * var(--cameraSpeed) * 481 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(482) { + transform: translate3D(18.4%, 228%, calc(var(--itemZ) * var(--cameraSpeed) * 482 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(483) { + transform: translate3D(8.3%, 124%, calc(var(--itemZ) * var(--cameraSpeed) * 483 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(484) { + transform: translate3D(11.1%, 253%, calc(var(--itemZ) * var(--cameraSpeed) * 484 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(485) { + transform: translate3D(10.3%, 88%, calc(var(--itemZ) * var(--cameraSpeed) * 485 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(486) { + transform: translate3D(15.5%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 486 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(487) { + transform: translate3D(7.7%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 487 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(488) { + transform: translate3D(12.1%, 176%, calc(var(--itemZ) * var(--cameraSpeed) * 488 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(489) { + transform: translate3D(19.5%, 178%, calc(var(--itemZ) * var(--cameraSpeed) * 489 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(490) { + transform: translate3D(12.7%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 490 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(491) { + transform: translate3D(10.6%, 122%, calc(var(--itemZ) * var(--cameraSpeed) * 491 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(492) { + transform: translate3D(16.2%, 186%, calc(var(--itemZ) * var(--cameraSpeed) * 492 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(493) { + transform: translate3D(3.6%, 250%, calc(var(--itemZ) * var(--cameraSpeed) * 493 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(494) { + transform: translate3D(9.1%, 60%, calc(var(--itemZ) * var(--cameraSpeed) * 494 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(495) { + transform: translate3D(18.8%, 184%, calc(var(--itemZ) * var(--cameraSpeed) * 495 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(496) { + transform: translate3D(4.1%, 127%, calc(var(--itemZ) * var(--cameraSpeed) * 496 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(497) { + transform: translate3D(6%, 156%, calc(var(--itemZ) * var(--cameraSpeed) * 497 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(498) { + transform: translate3D(3.2%, 236%, calc(var(--itemZ) * var(--cameraSpeed) * 498 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(499) { + transform: translate3D(8.5%, 37%, calc(var(--itemZ) * var(--cameraSpeed) * 499 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(500) { + transform: translate3D(3.5%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 500 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(501) { + transform: translate3D(8%, 37%, calc(var(--itemZ) * var(--cameraSpeed) * 501 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(502) { + transform: translate3D(11.9%, 236%, calc(var(--itemZ) * var(--cameraSpeed) * 502 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(503) { + transform: translate3D(1.1%, 173%, calc(var(--itemZ) * var(--cameraSpeed) * 503 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(504) { + transform: translate3D(17.4%, 27%, calc(var(--itemZ) * var(--cameraSpeed) * 504 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(505) { + transform: translate3D(18.6%, 102%, calc(var(--itemZ) * var(--cameraSpeed) * 505 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(506) { + transform: translate3D(1.4%, 163%, calc(var(--itemZ) * var(--cameraSpeed) * 506 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(507) { + transform: translate3D(3.6%, 19%, calc(var(--itemZ) * var(--cameraSpeed) * 507 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(508) { + transform: translate3D(4.5%, 257%, calc(var(--itemZ) * var(--cameraSpeed) * 508 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(509) { + transform: translate3D(10.5%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 509 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(510) { + transform: translate3D(19.1%, 18%, calc(var(--itemZ) * var(--cameraSpeed) * 510 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(511) { + transform: translate3D(15.8%, 172%, calc(var(--itemZ) * var(--cameraSpeed) * 511 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(512) { + transform: translate3D(4.5%, 128%, calc(var(--itemZ) * var(--cameraSpeed) * 512 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(513) { + transform: translate3D(18.7%, 256%, calc(var(--itemZ) * var(--cameraSpeed) * 513 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(514) { + transform: translate3D(0.5%, 234%, calc(var(--itemZ) * var(--cameraSpeed) * 514 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(515) { + transform: translate3D(18.5%, 88%, calc(var(--itemZ) * var(--cameraSpeed) * 515 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(516) { + transform: translate3D(0.1%, 36%, calc(var(--itemZ) * var(--cameraSpeed) * 516 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(517) { + transform: translate3D(5.3%, 62%, calc(var(--itemZ) * var(--cameraSpeed) * 517 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(518) { + transform: translate3D(11%, 245%, calc(var(--itemZ) * var(--cameraSpeed) * 518 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(519) { + transform: translate3D(1.7%, 115%, calc(var(--itemZ) * var(--cameraSpeed) * 519 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(520) { + transform: translate3D(9.5%, 225%, calc(var(--itemZ) * var(--cameraSpeed) * 520 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(521) { + transform: translate3D(17.3%, 92%, calc(var(--itemZ) * var(--cameraSpeed) * 521 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(522) { + transform: translate3D(5.2%, 182%, calc(var(--itemZ) * var(--cameraSpeed) * 522 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(523) { + transform: translate3D(11.7%, 94%, calc(var(--itemZ) * var(--cameraSpeed) * 523 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(524) { + transform: translate3D(5.8%, 275%, calc(var(--itemZ) * var(--cameraSpeed) * 524 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(525) { + transform: translate3D(6.9%, 190%, calc(var(--itemZ) * var(--cameraSpeed) * 525 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(526) { + transform: translate3D(15.9%, 212%, calc(var(--itemZ) * var(--cameraSpeed) * 526 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(527) { + transform: translate3D(14%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 527 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(528) { + transform: translate3D(13.2%, 131%, calc(var(--itemZ) * var(--cameraSpeed) * 528 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(529) { + transform: translate3D(0.7%, 172%, calc(var(--itemZ) * var(--cameraSpeed) * 529 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(530) { + transform: translate3D(4.7%, 167%, calc(var(--itemZ) * var(--cameraSpeed) * 530 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(531) { + transform: translate3D(15.5%, 186%, calc(var(--itemZ) * var(--cameraSpeed) * 531 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(532) { + transform: translate3D(4.3%, 255%, calc(var(--itemZ) * var(--cameraSpeed) * 532 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(533) { + transform: translate3D(16%, 15%, calc(var(--itemZ) * var(--cameraSpeed) * 533 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(534) { + transform: translate3D(1.2%, 136%, calc(var(--itemZ) * var(--cameraSpeed) * 534 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(535) { + transform: translate3D(19.9%, 121%, calc(var(--itemZ) * var(--cameraSpeed) * 535 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(536) { + transform: translate3D(0.6%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 536 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(537) { + transform: translate3D(14.9%, 141%, calc(var(--itemZ) * var(--cameraSpeed) * 537 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(538) { + transform: translate3D(19.8%, 127%, calc(var(--itemZ) * var(--cameraSpeed) * 538 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(539) { + transform: translate3D(10.1%, 81%, calc(var(--itemZ) * var(--cameraSpeed) * 539 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(540) { + transform: translate3D(12.9%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 540 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(541) { + transform: translate3D(11.1%, 50%, calc(var(--itemZ) * var(--cameraSpeed) * 541 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(542) { + transform: translate3D(5.5%, 34%, calc(var(--itemZ) * var(--cameraSpeed) * 542 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(543) { + transform: translate3D(3.5%, 272%, calc(var(--itemZ) * var(--cameraSpeed) * 543 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(544) { + transform: translate3D(8.7%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 544 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(545) { + transform: translate3D(1.7%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 545 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(546) { + transform: translate3D(5.8%, 114%, calc(var(--itemZ) * var(--cameraSpeed) * 546 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(547) { + transform: translate3D(9.6%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 547 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(548) { + transform: translate3D(14.9%, 214%, calc(var(--itemZ) * var(--cameraSpeed) * 548 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(549) { + transform: translate3D(2%, 120%, calc(var(--itemZ) * var(--cameraSpeed) * 549 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(550) { + transform: translate3D(0.1%, 108%, calc(var(--itemZ) * var(--cameraSpeed) * 550 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(551) { + transform: translate3D(4.5%, 32%, calc(var(--itemZ) * var(--cameraSpeed) * 551 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(552) { + transform: translate3D(8.5%, 77%, calc(var(--itemZ) * var(--cameraSpeed) * 552 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(553) { + transform: translate3D(6.9%, 193%, calc(var(--itemZ) * var(--cameraSpeed) * 553 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(554) { + transform: translate3D(11.5%, 288%, calc(var(--itemZ) * var(--cameraSpeed) * 554 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(555) { + transform: translate3D(1.9%, 115%, calc(var(--itemZ) * var(--cameraSpeed) * 555 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(556) { + transform: translate3D(8.2%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 556 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(557) { + transform: translate3D(10.7%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 557 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(558) { + transform: translate3D(0.9%, 75%, calc(var(--itemZ) * var(--cameraSpeed) * 558 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(559) { + transform: translate3D(15.4%, 18%, calc(var(--itemZ) * var(--cameraSpeed) * 559 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(560) { + transform: translate3D(16.4%, 45%, calc(var(--itemZ) * var(--cameraSpeed) * 560 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(561) { + transform: translate3D(11.4%, 249%, calc(var(--itemZ) * var(--cameraSpeed) * 561 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(562) { + transform: translate3D(13.7%, 149%, calc(var(--itemZ) * var(--cameraSpeed) * 562 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(563) { + transform: translate3D(14.7%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 563 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(564) { + transform: translate3D(0.6%, 54%, calc(var(--itemZ) * var(--cameraSpeed) * 564 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(565) { + transform: translate3D(9.8%, 152%, calc(var(--itemZ) * var(--cameraSpeed) * 565 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(566) { + transform: translate3D(10.6%, 114%, calc(var(--itemZ) * var(--cameraSpeed) * 566 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(567) { + transform: translate3D(15.4%, 272%, calc(var(--itemZ) * var(--cameraSpeed) * 567 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(568) { + transform: translate3D(9.3%, 172%, calc(var(--itemZ) * var(--cameraSpeed) * 568 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(569) { + transform: translate3D(6.4%, 211%, calc(var(--itemZ) * var(--cameraSpeed) * 569 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(570) { + transform: translate3D(18.5%, 57%, calc(var(--itemZ) * var(--cameraSpeed) * 570 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(571) { + transform: translate3D(5.6%, 84%, calc(var(--itemZ) * var(--cameraSpeed) * 571 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(572) { + transform: translate3D(11.5%, 222%, calc(var(--itemZ) * var(--cameraSpeed) * 572 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(573) { + transform: translate3D(0.4%, 294%, calc(var(--itemZ) * var(--cameraSpeed) * 573 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(574) { + transform: translate3D(13%, 105%, calc(var(--itemZ) * var(--cameraSpeed) * 574 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(575) { + transform: translate3D(13.5%, 77%, calc(var(--itemZ) * var(--cameraSpeed) * 575 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(576) { + transform: translate3D(3.9%, 204%, calc(var(--itemZ) * var(--cameraSpeed) * 576 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(577) { + transform: translate3D(13.5%, 296%, calc(var(--itemZ) * var(--cameraSpeed) * 577 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(578) { + transform: translate3D(17.5%, 283%, calc(var(--itemZ) * var(--cameraSpeed) * 578 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(579) { + transform: translate3D(16.1%, 125%, calc(var(--itemZ) * var(--cameraSpeed) * 579 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(580) { + transform: translate3D(12%, 150%, calc(var(--itemZ) * var(--cameraSpeed) * 580 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(581) { + transform: translate3D(2.9%, 31%, calc(var(--itemZ) * var(--cameraSpeed) * 581 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(582) { + transform: translate3D(17.6%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 582 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(583) { + transform: translate3D(12.3%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 583 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(584) { + transform: translate3D(5.9%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 584 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(585) { + transform: translate3D(2%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 585 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(586) { + transform: translate3D(14.7%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 586 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(587) { + transform: translate3D(9.6%, 252%, calc(var(--itemZ) * var(--cameraSpeed) * 587 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(588) { + transform: translate3D(6.6%, 236%, calc(var(--itemZ) * var(--cameraSpeed) * 588 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(589) { + transform: translate3D(14.4%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 589 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(590) { + transform: translate3D(14%, 136%, calc(var(--itemZ) * var(--cameraSpeed) * 590 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(591) { + transform: translate3D(2.7%, 156%, calc(var(--itemZ) * var(--cameraSpeed) * 591 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(592) { + transform: translate3D(18.1%, 65%, calc(var(--itemZ) * var(--cameraSpeed) * 592 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(593) { + transform: translate3D(11.6%, 167%, calc(var(--itemZ) * var(--cameraSpeed) * 593 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(594) { + transform: translate3D(9.9%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 594 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(595) { + transform: translate3D(17.9%, 145%, calc(var(--itemZ) * var(--cameraSpeed) * 595 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(596) { + transform: translate3D(16.3%, 258%, calc(var(--itemZ) * var(--cameraSpeed) * 596 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(597) { + transform: translate3D(18.4%, 203%, calc(var(--itemZ) * var(--cameraSpeed) * 597 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(598) { + transform: translate3D(2.2%, 21%, calc(var(--itemZ) * var(--cameraSpeed) * 598 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(599) { + transform: translate3D(10.3%, 282%, calc(var(--itemZ) * var(--cameraSpeed) * 599 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(600) { + transform: translate3D(5.8%, 259%, calc(var(--itemZ) * var(--cameraSpeed) * 600 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(601) { + transform: translate3D(12.4%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 601 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(602) { + transform: translate3D(19.4%, 158%, calc(var(--itemZ) * var(--cameraSpeed) * 602 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(603) { + transform: translate3D(17.3%, 29%, calc(var(--itemZ) * var(--cameraSpeed) * 603 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(604) { + transform: translate3D(11.6%, 236%, calc(var(--itemZ) * var(--cameraSpeed) * 604 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(605) { + transform: translate3D(3.6%, 126%, calc(var(--itemZ) * var(--cameraSpeed) * 605 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(606) { + transform: translate3D(12.1%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 606 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(607) { + transform: translate3D(12.2%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 607 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(608) { + transform: translate3D(11.3%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 608 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(609) { + transform: translate3D(19.3%, 205%, calc(var(--itemZ) * var(--cameraSpeed) * 609 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(610) { + transform: translate3D(15.1%, 143%, calc(var(--itemZ) * var(--cameraSpeed) * 610 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(611) { + transform: translate3D(11.5%, 228%, calc(var(--itemZ) * var(--cameraSpeed) * 611 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(612) { + transform: translate3D(4%, 147%, calc(var(--itemZ) * var(--cameraSpeed) * 612 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(613) { + transform: translate3D(2.5%, 266%, calc(var(--itemZ) * var(--cameraSpeed) * 613 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(614) { + transform: translate3D(8.4%, 183%, calc(var(--itemZ) * var(--cameraSpeed) * 614 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(615) { + transform: translate3D(5.3%, 300%, calc(var(--itemZ) * var(--cameraSpeed) * 615 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(616) { + transform: translate3D(16.7%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 616 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(617) { + transform: translate3D(6.1%, 248%, calc(var(--itemZ) * var(--cameraSpeed) * 617 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(618) { + transform: translate3D(19.2%, 232%, calc(var(--itemZ) * var(--cameraSpeed) * 618 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(619) { + transform: translate3D(15.3%, 175%, calc(var(--itemZ) * var(--cameraSpeed) * 619 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(620) { + transform: translate3D(0.8%, 44%, calc(var(--itemZ) * var(--cameraSpeed) * 620 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(621) { + transform: translate3D(15.9%, 157%, calc(var(--itemZ) * var(--cameraSpeed) * 621 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(622) { + transform: translate3D(7.7%, 253%, calc(var(--itemZ) * var(--cameraSpeed) * 622 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(623) { + transform: translate3D(7%, 261%, calc(var(--itemZ) * var(--cameraSpeed) * 623 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(624) { + transform: translate3D(1.9%, 184%, calc(var(--itemZ) * var(--cameraSpeed) * 624 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(625) { + transform: translate3D(2.6%, 262%, calc(var(--itemZ) * var(--cameraSpeed) * 625 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(626) { + transform: translate3D(9.7%, 285%, calc(var(--itemZ) * var(--cameraSpeed) * 626 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(627) { + transform: translate3D(3.3%, 267%, calc(var(--itemZ) * var(--cameraSpeed) * 627 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(628) { + transform: translate3D(17.5%, 96%, calc(var(--itemZ) * var(--cameraSpeed) * 628 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(629) { + transform: translate3D(11%, 18%, calc(var(--itemZ) * var(--cameraSpeed) * 629 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(630) { + transform: translate3D(11.9%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 630 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(631) { + transform: translate3D(7.7%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 631 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(632) { + transform: translate3D(18.5%, 185%, calc(var(--itemZ) * var(--cameraSpeed) * 632 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(633) { + transform: translate3D(15.5%, 137%, calc(var(--itemZ) * var(--cameraSpeed) * 633 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(634) { + transform: translate3D(3.2%, 168%, calc(var(--itemZ) * var(--cameraSpeed) * 634 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(635) { + transform: translate3D(7.4%, 78%, calc(var(--itemZ) * var(--cameraSpeed) * 635 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(636) { + transform: translate3D(9.6%, 106%, calc(var(--itemZ) * var(--cameraSpeed) * 636 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(637) { + transform: translate3D(18%, 50%, calc(var(--itemZ) * var(--cameraSpeed) * 637 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(638) { + transform: translate3D(6.5%, 161%, calc(var(--itemZ) * var(--cameraSpeed) * 638 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(639) { + transform: translate3D(8.5%, 249%, calc(var(--itemZ) * var(--cameraSpeed) * 639 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(640) { + transform: translate3D(17.9%, 295%, calc(var(--itemZ) * var(--cameraSpeed) * 640 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(641) { + transform: translate3D(11.3%, 248%, calc(var(--itemZ) * var(--cameraSpeed) * 641 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(642) { + transform: translate3D(8.2%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 642 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(643) { + transform: translate3D(8.2%, 188%, calc(var(--itemZ) * var(--cameraSpeed) * 643 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(644) { + transform: translate3D(4.1%, 111%, calc(var(--itemZ) * var(--cameraSpeed) * 644 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(645) { + transform: translate3D(14.2%, 49%, calc(var(--itemZ) * var(--cameraSpeed) * 645 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(646) { + transform: translate3D(15.2%, 170%, calc(var(--itemZ) * var(--cameraSpeed) * 646 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(647) { + transform: translate3D(11.7%, 172%, calc(var(--itemZ) * var(--cameraSpeed) * 647 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(648) { + transform: translate3D(16.1%, 288%, calc(var(--itemZ) * var(--cameraSpeed) * 648 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(649) { + transform: translate3D(17.4%, 224%, calc(var(--itemZ) * var(--cameraSpeed) * 649 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(650) { + transform: translate3D(11.2%, 81%, calc(var(--itemZ) * var(--cameraSpeed) * 650 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(651) { + transform: translate3D(7.7%, 72%, calc(var(--itemZ) * var(--cameraSpeed) * 651 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(652) { + transform: translate3D(1.6%, 253%, calc(var(--itemZ) * var(--cameraSpeed) * 652 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(653) { + transform: translate3D(4.7%, 16%, calc(var(--itemZ) * var(--cameraSpeed) * 653 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(654) { + transform: translate3D(1.1%, 38%, calc(var(--itemZ) * var(--cameraSpeed) * 654 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(655) { + transform: translate3D(9.7%, 120%, calc(var(--itemZ) * var(--cameraSpeed) * 655 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(656) { + transform: translate3D(7.5%, 97%, calc(var(--itemZ) * var(--cameraSpeed) * 656 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(657) { + transform: translate3D(6.6%, 287%, calc(var(--itemZ) * var(--cameraSpeed) * 657 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(658) { + transform: translate3D(6.9%, 132%, calc(var(--itemZ) * var(--cameraSpeed) * 658 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(659) { + transform: translate3D(16.4%, 220%, calc(var(--itemZ) * var(--cameraSpeed) * 659 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(660) { + transform: translate3D(16.8%, 78%, calc(var(--itemZ) * var(--cameraSpeed) * 660 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(661) { + transform: translate3D(3.1%, 99%, calc(var(--itemZ) * var(--cameraSpeed) * 661 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(662) { + transform: translate3D(1.2%, 291%, calc(var(--itemZ) * var(--cameraSpeed) * 662 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(663) { + transform: translate3D(18.5%, 60%, calc(var(--itemZ) * var(--cameraSpeed) * 663 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(664) { + transform: translate3D(9.7%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 664 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(665) { + transform: translate3D(2.7%, 62%, calc(var(--itemZ) * var(--cameraSpeed) * 665 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(666) { + transform: translate3D(19.4%, 240%, calc(var(--itemZ) * var(--cameraSpeed) * 666 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(667) { + transform: translate3D(13.7%, 201%, calc(var(--itemZ) * var(--cameraSpeed) * 667 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(668) { + transform: translate3D(10.4%, 7%, calc(var(--itemZ) * var(--cameraSpeed) * 668 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(669) { + transform: translate3D(3%, 289%, calc(var(--itemZ) * var(--cameraSpeed) * 669 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(670) { + transform: translate3D(2.6%, 184%, calc(var(--itemZ) * var(--cameraSpeed) * 670 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(671) { + transform: translate3D(9.5%, 270%, calc(var(--itemZ) * var(--cameraSpeed) * 671 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(672) { + transform: translate3D(12.3%, 47%, calc(var(--itemZ) * var(--cameraSpeed) * 672 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(673) { + transform: translate3D(13.4%, 75%, calc(var(--itemZ) * var(--cameraSpeed) * 673 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(674) { + transform: translate3D(1.2%, 278%, calc(var(--itemZ) * var(--cameraSpeed) * 674 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(675) { + transform: translate3D(14.2%, 26%, calc(var(--itemZ) * var(--cameraSpeed) * 675 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(676) { + transform: translate3D(17%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 676 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(677) { + transform: translate3D(4.4%, 144%, calc(var(--itemZ) * var(--cameraSpeed) * 677 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(678) { + transform: translate3D(11.9%, 167%, calc(var(--itemZ) * var(--cameraSpeed) * 678 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(679) { + transform: translate3D(5.2%, 268%, calc(var(--itemZ) * var(--cameraSpeed) * 679 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(680) { + transform: translate3D(5%, 189%, calc(var(--itemZ) * var(--cameraSpeed) * 680 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(681) { + transform: translate3D(8.5%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 681 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(682) { + transform: translate3D(20%, 130%, calc(var(--itemZ) * var(--cameraSpeed) * 682 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(683) { + transform: translate3D(7.4%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 683 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(684) { + transform: translate3D(2.4%, 29%, calc(var(--itemZ) * var(--cameraSpeed) * 684 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(685) { + transform: translate3D(15.1%, 284%, calc(var(--itemZ) * var(--cameraSpeed) * 685 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(686) { + transform: translate3D(5.4%, 171%, calc(var(--itemZ) * var(--cameraSpeed) * 686 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(687) { + transform: translate3D(16%, 156%, calc(var(--itemZ) * var(--cameraSpeed) * 687 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(688) { + transform: translate3D(6.2%, 272%, calc(var(--itemZ) * var(--cameraSpeed) * 688 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(689) { + transform: translate3D(7.9%, 103%, calc(var(--itemZ) * var(--cameraSpeed) * 689 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(690) { + transform: translate3D(15.9%, 195%, calc(var(--itemZ) * var(--cameraSpeed) * 690 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(691) { + transform: translate3D(3.8%, 14%, calc(var(--itemZ) * var(--cameraSpeed) * 691 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(692) { + transform: translate3D(18%, 145%, calc(var(--itemZ) * var(--cameraSpeed) * 692 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(693) { + transform: translate3D(18%, 286%, calc(var(--itemZ) * var(--cameraSpeed) * 693 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(694) { + transform: translate3D(17.3%, 231%, calc(var(--itemZ) * var(--cameraSpeed) * 694 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(695) { + transform: translate3D(5%, 110%, calc(var(--itemZ) * var(--cameraSpeed) * 695 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(696) { + transform: translate3D(10%, 14%, calc(var(--itemZ) * var(--cameraSpeed) * 696 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(697) { + transform: translate3D(19.1%, 96%, calc(var(--itemZ) * var(--cameraSpeed) * 697 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(698) { + transform: translate3D(19.1%, 87%, calc(var(--itemZ) * var(--cameraSpeed) * 698 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(699) { + transform: translate3D(14.5%, 112%, calc(var(--itemZ) * var(--cameraSpeed) * 699 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(700) { + transform: translate3D(13.2%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 700 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(701) { + transform: translate3D(17.9%, 42%, calc(var(--itemZ) * var(--cameraSpeed) * 701 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(702) { + transform: translate3D(15.9%, 266%, calc(var(--itemZ) * var(--cameraSpeed) * 702 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(703) { + transform: translate3D(10.3%, 288%, calc(var(--itemZ) * var(--cameraSpeed) * 703 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(704) { + transform: translate3D(5.6%, 238%, calc(var(--itemZ) * var(--cameraSpeed) * 704 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(705) { + transform: translate3D(18.2%, 240%, calc(var(--itemZ) * var(--cameraSpeed) * 705 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(706) { + transform: translate3D(1%, 78%, calc(var(--itemZ) * var(--cameraSpeed) * 706 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(707) { + transform: translate3D(11%, 226%, calc(var(--itemZ) * var(--cameraSpeed) * 707 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(708) { + transform: translate3D(7.9%, 54%, calc(var(--itemZ) * var(--cameraSpeed) * 708 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(709) { + transform: translate3D(18.3%, 152%, calc(var(--itemZ) * var(--cameraSpeed) * 709 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(710) { + transform: translate3D(0.6%, 133%, calc(var(--itemZ) * var(--cameraSpeed) * 710 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(711) { + transform: translate3D(10.5%, 1%, calc(var(--itemZ) * var(--cameraSpeed) * 711 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(712) { + transform: translate3D(15.7%, 97%, calc(var(--itemZ) * var(--cameraSpeed) * 712 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(713) { + transform: translate3D(16.6%, 117%, calc(var(--itemZ) * var(--cameraSpeed) * 713 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(714) { + transform: translate3D(4.9%, 225%, calc(var(--itemZ) * var(--cameraSpeed) * 714 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(715) { + transform: translate3D(2.4%, 95%, calc(var(--itemZ) * var(--cameraSpeed) * 715 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(716) { + transform: translate3D(12.5%, 128%, calc(var(--itemZ) * var(--cameraSpeed) * 716 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(717) { + transform: translate3D(5.9%, 117%, calc(var(--itemZ) * var(--cameraSpeed) * 717 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(718) { + transform: translate3D(9.6%, 298%, calc(var(--itemZ) * var(--cameraSpeed) * 718 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(719) { + transform: translate3D(12.7%, 90%, calc(var(--itemZ) * var(--cameraSpeed) * 719 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(720) { + transform: translate3D(10.5%, 133%, calc(var(--itemZ) * var(--cameraSpeed) * 720 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(721) { + transform: translate3D(8.3%, 75%, calc(var(--itemZ) * var(--cameraSpeed) * 721 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(722) { + transform: translate3D(7.1%, 106%, calc(var(--itemZ) * var(--cameraSpeed) * 722 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(723) { + transform: translate3D(4.8%, 163%, calc(var(--itemZ) * var(--cameraSpeed) * 723 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(724) { + transform: translate3D(6.5%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 724 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(725) { + transform: translate3D(10.2%, 87%, calc(var(--itemZ) * var(--cameraSpeed) * 725 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(726) { + transform: translate3D(13.2%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 726 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(727) { + transform: translate3D(7.8%, 34%, calc(var(--itemZ) * var(--cameraSpeed) * 727 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(728) { + transform: translate3D(5.2%, 173%, calc(var(--itemZ) * var(--cameraSpeed) * 728 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(729) { + transform: translate3D(17.2%, 297%, calc(var(--itemZ) * var(--cameraSpeed) * 729 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(730) { + transform: translate3D(2.2%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 730 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(731) { + transform: translate3D(2.3%, 299%, calc(var(--itemZ) * var(--cameraSpeed) * 731 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(732) { + transform: translate3D(14.7%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 732 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(733) { + transform: translate3D(16.7%, 186%, calc(var(--itemZ) * var(--cameraSpeed) * 733 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(734) { + transform: translate3D(0.8%, 240%, calc(var(--itemZ) * var(--cameraSpeed) * 734 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(735) { + transform: translate3D(1.7%, 133%, calc(var(--itemZ) * var(--cameraSpeed) * 735 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(736) { + transform: translate3D(13.3%, 182%, calc(var(--itemZ) * var(--cameraSpeed) * 736 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(737) { + transform: translate3D(14.9%, 166%, calc(var(--itemZ) * var(--cameraSpeed) * 737 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(738) { + transform: translate3D(0.8%, 89%, calc(var(--itemZ) * var(--cameraSpeed) * 738 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(739) { + transform: translate3D(13.5%, 188%, calc(var(--itemZ) * var(--cameraSpeed) * 739 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(740) { + transform: translate3D(9.2%, 64%, calc(var(--itemZ) * var(--cameraSpeed) * 740 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(741) { + transform: translate3D(4.9%, 84%, calc(var(--itemZ) * var(--cameraSpeed) * 741 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(742) { + transform: translate3D(1.6%, 224%, calc(var(--itemZ) * var(--cameraSpeed) * 742 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(743) { + transform: translate3D(13.7%, 127%, calc(var(--itemZ) * var(--cameraSpeed) * 743 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(744) { + transform: translate3D(2.1%, 82%, calc(var(--itemZ) * var(--cameraSpeed) * 744 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(745) { + transform: translate3D(6.1%, 216%, calc(var(--itemZ) * var(--cameraSpeed) * 745 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(746) { + transform: translate3D(11.7%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 746 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(747) { + transform: translate3D(2.1%, 127%, calc(var(--itemZ) * var(--cameraSpeed) * 747 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(748) { + transform: translate3D(16.6%, 222%, calc(var(--itemZ) * var(--cameraSpeed) * 748 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(749) { + transform: translate3D(12.9%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 749 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(750) { + transform: translate3D(9%, 113%, calc(var(--itemZ) * var(--cameraSpeed) * 750 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(751) { + transform: translate3D(11.6%, 63%, calc(var(--itemZ) * var(--cameraSpeed) * 751 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(752) { + transform: translate3D(1.7%, 245%, calc(var(--itemZ) * var(--cameraSpeed) * 752 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(753) { + transform: translate3D(14.9%, 290%, calc(var(--itemZ) * var(--cameraSpeed) * 753 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(754) { + transform: translate3D(6.8%, 116%, calc(var(--itemZ) * var(--cameraSpeed) * 754 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(755) { + transform: translate3D(4.5%, 149%, calc(var(--itemZ) * var(--cameraSpeed) * 755 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(756) { + transform: translate3D(3.9%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 756 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(757) { + transform: translate3D(16.1%, 108%, calc(var(--itemZ) * var(--cameraSpeed) * 757 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(758) { + transform: translate3D(11.5%, 182%, calc(var(--itemZ) * var(--cameraSpeed) * 758 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(759) { + transform: translate3D(12.6%, 48%, calc(var(--itemZ) * var(--cameraSpeed) * 759 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(760) { + transform: translate3D(12.8%, 62%, calc(var(--itemZ) * var(--cameraSpeed) * 760 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(761) { + transform: translate3D(1.5%, 62%, calc(var(--itemZ) * var(--cameraSpeed) * 761 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(762) { + transform: translate3D(11.2%, 228%, calc(var(--itemZ) * var(--cameraSpeed) * 762 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(763) { + transform: translate3D(0.8%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 763 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(764) { + transform: translate3D(19.1%, 160%, calc(var(--itemZ) * var(--cameraSpeed) * 764 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(765) { + transform: translate3D(0.4%, 280%, calc(var(--itemZ) * var(--cameraSpeed) * 765 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(766) { + transform: translate3D(15.9%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 766 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(767) { + transform: translate3D(16.8%, 169%, calc(var(--itemZ) * var(--cameraSpeed) * 767 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(768) { + transform: translate3D(1.6%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 768 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(769) { + transform: translate3D(18.1%, 278%, calc(var(--itemZ) * var(--cameraSpeed) * 769 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(770) { + transform: translate3D(13.1%, 276%, calc(var(--itemZ) * var(--cameraSpeed) * 770 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(771) { + transform: translate3D(17.4%, 129%, calc(var(--itemZ) * var(--cameraSpeed) * 771 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(772) { + transform: translate3D(15.7%, 183%, calc(var(--itemZ) * var(--cameraSpeed) * 772 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(773) { + transform: translate3D(12.1%, 187%, calc(var(--itemZ) * var(--cameraSpeed) * 773 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(774) { + transform: translate3D(12.2%, 251%, calc(var(--itemZ) * var(--cameraSpeed) * 774 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(775) { + transform: translate3D(2.8%, 248%, calc(var(--itemZ) * var(--cameraSpeed) * 775 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(776) { + transform: translate3D(19.6%, 69%, calc(var(--itemZ) * var(--cameraSpeed) * 776 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(777) { + transform: translate3D(4.3%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 777 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(778) { + transform: translate3D(5.9%, 173%, calc(var(--itemZ) * var(--cameraSpeed) * 778 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(779) { + transform: translate3D(4.2%, 153%, calc(var(--itemZ) * var(--cameraSpeed) * 779 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(780) { + transform: translate3D(14.4%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 780 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(781) { + transform: translate3D(13%, 203%, calc(var(--itemZ) * var(--cameraSpeed) * 781 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(782) { + transform: translate3D(18.2%, 62%, calc(var(--itemZ) * var(--cameraSpeed) * 782 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(783) { + transform: translate3D(9.3%, 172%, calc(var(--itemZ) * var(--cameraSpeed) * 783 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(784) { + transform: translate3D(12.4%, 164%, calc(var(--itemZ) * var(--cameraSpeed) * 784 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(785) { + transform: translate3D(15.6%, 134%, calc(var(--itemZ) * var(--cameraSpeed) * 785 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(786) { + transform: translate3D(6.4%, 216%, calc(var(--itemZ) * var(--cameraSpeed) * 786 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(787) { + transform: translate3D(1.7%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 787 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(788) { + transform: translate3D(12.1%, 87%, calc(var(--itemZ) * var(--cameraSpeed) * 788 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(789) { + transform: translate3D(16.9%, 61%, calc(var(--itemZ) * var(--cameraSpeed) * 789 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(790) { + transform: translate3D(4%, 148%, calc(var(--itemZ) * var(--cameraSpeed) * 790 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(791) { + transform: translate3D(15.1%, 244%, calc(var(--itemZ) * var(--cameraSpeed) * 791 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(792) { + transform: translate3D(3.1%, 220%, calc(var(--itemZ) * var(--cameraSpeed) * 792 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(793) { + transform: translate3D(4.6%, 274%, calc(var(--itemZ) * var(--cameraSpeed) * 793 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(794) { + transform: translate3D(8.7%, 110%, calc(var(--itemZ) * var(--cameraSpeed) * 794 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(795) { + transform: translate3D(12.7%, 199%, calc(var(--itemZ) * var(--cameraSpeed) * 795 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(796) { + transform: translate3D(11.5%, 150%, calc(var(--itemZ) * var(--cameraSpeed) * 796 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(797) { + transform: translate3D(16.6%, 268%, calc(var(--itemZ) * var(--cameraSpeed) * 797 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(798) { + transform: translate3D(1.9%, 80%, calc(var(--itemZ) * var(--cameraSpeed) * 798 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(799) { + transform: translate3D(17.2%, 231%, calc(var(--itemZ) * var(--cameraSpeed) * 799 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(800) { + transform: translate3D(11.2%, 33%, calc(var(--itemZ) * var(--cameraSpeed) * 800 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(801) { + transform: translate3D(12%, 14%, calc(var(--itemZ) * var(--cameraSpeed) * 801 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(802) { + transform: translate3D(12.6%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 802 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(803) { + transform: translate3D(6.4%, 246%, calc(var(--itemZ) * var(--cameraSpeed) * 803 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(804) { + transform: translate3D(12%, 218%, calc(var(--itemZ) * var(--cameraSpeed) * 804 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(805) { + transform: translate3D(12.1%, 174%, calc(var(--itemZ) * var(--cameraSpeed) * 805 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(806) { + transform: translate3D(9.8%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 806 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(807) { + transform: translate3D(0.9%, 98%, calc(var(--itemZ) * var(--cameraSpeed) * 807 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(808) { + transform: translate3D(12.8%, 176%, calc(var(--itemZ) * var(--cameraSpeed) * 808 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(809) { + transform: translate3D(15.3%, 191%, calc(var(--itemZ) * var(--cameraSpeed) * 809 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(810) { + transform: translate3D(3.4%, 294%, calc(var(--itemZ) * var(--cameraSpeed) * 810 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(811) { + transform: translate3D(4.2%, 216%, calc(var(--itemZ) * var(--cameraSpeed) * 811 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(812) { + transform: translate3D(7.6%, 211%, calc(var(--itemZ) * var(--cameraSpeed) * 812 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(813) { + transform: translate3D(19.3%, 51%, calc(var(--itemZ) * var(--cameraSpeed) * 813 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(814) { + transform: translate3D(5.1%, 108%, calc(var(--itemZ) * var(--cameraSpeed) * 814 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(815) { + transform: translate3D(2.3%, 186%, calc(var(--itemZ) * var(--cameraSpeed) * 815 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(816) { + transform: translate3D(7.8%, 107%, calc(var(--itemZ) * var(--cameraSpeed) * 816 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(817) { + transform: translate3D(9.6%, 217%, calc(var(--itemZ) * var(--cameraSpeed) * 817 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(818) { + transform: translate3D(7.8%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 818 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(819) { + transform: translate3D(7.7%, 95%, calc(var(--itemZ) * var(--cameraSpeed) * 819 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(820) { + transform: translate3D(5.2%, 286%, calc(var(--itemZ) * var(--cameraSpeed) * 820 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(821) { + transform: translate3D(18.7%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 821 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(822) { + transform: translate3D(6.5%, 142%, calc(var(--itemZ) * var(--cameraSpeed) * 822 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(823) { + transform: translate3D(9.2%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 823 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(824) { + transform: translate3D(15.7%, 10%, calc(var(--itemZ) * var(--cameraSpeed) * 824 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(825) { + transform: translate3D(13.8%, 188%, calc(var(--itemZ) * var(--cameraSpeed) * 825 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(826) { + transform: translate3D(16.8%, 94%, calc(var(--itemZ) * var(--cameraSpeed) * 826 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(827) { + transform: translate3D(18.7%, 97%, calc(var(--itemZ) * var(--cameraSpeed) * 827 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(828) { + transform: translate3D(11.4%, 120%, calc(var(--itemZ) * var(--cameraSpeed) * 828 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(829) { + transform: translate3D(16.8%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 829 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(830) { + transform: translate3D(13%, 219%, calc(var(--itemZ) * var(--cameraSpeed) * 830 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(831) { + transform: translate3D(0.6%, 75%, calc(var(--itemZ) * var(--cameraSpeed) * 831 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(832) { + transform: translate3D(6.9%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 832 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(833) { + transform: translate3D(4.4%, 269%, calc(var(--itemZ) * var(--cameraSpeed) * 833 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(834) { + transform: translate3D(14.4%, 246%, calc(var(--itemZ) * var(--cameraSpeed) * 834 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(835) { + transform: translate3D(0.4%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 835 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(836) { + transform: translate3D(2%, 292%, calc(var(--itemZ) * var(--cameraSpeed) * 836 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(837) { + transform: translate3D(18.6%, 206%, calc(var(--itemZ) * var(--cameraSpeed) * 837 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(838) { + transform: translate3D(13.5%, 92%, calc(var(--itemZ) * var(--cameraSpeed) * 838 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(839) { + transform: translate3D(15.2%, 48%, calc(var(--itemZ) * var(--cameraSpeed) * 839 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(840) { + transform: translate3D(15.2%, 265%, calc(var(--itemZ) * var(--cameraSpeed) * 840 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(841) { + transform: translate3D(9.7%, 121%, calc(var(--itemZ) * var(--cameraSpeed) * 841 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(842) { + transform: translate3D(7.3%, 24%, calc(var(--itemZ) * var(--cameraSpeed) * 842 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(843) { + transform: translate3D(8.1%, 201%, calc(var(--itemZ) * var(--cameraSpeed) * 843 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(844) { + transform: translate3D(2.1%, 57%, calc(var(--itemZ) * var(--cameraSpeed) * 844 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(845) { + transform: translate3D(14.4%, 46%, calc(var(--itemZ) * var(--cameraSpeed) * 845 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(846) { + transform: translate3D(8.8%, 6%, calc(var(--itemZ) * var(--cameraSpeed) * 846 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(847) { + transform: translate3D(12.8%, 178%, calc(var(--itemZ) * var(--cameraSpeed) * 847 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(848) { + transform: translate3D(2.9%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 848 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(849) { + transform: translate3D(12.1%, 94%, calc(var(--itemZ) * var(--cameraSpeed) * 849 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(850) { + transform: translate3D(4.7%, 56%, calc(var(--itemZ) * var(--cameraSpeed) * 850 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(851) { + transform: translate3D(16.4%, 264%, calc(var(--itemZ) * var(--cameraSpeed) * 851 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(852) { + transform: translate3D(13.3%, 8%, calc(var(--itemZ) * var(--cameraSpeed) * 852 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(853) { + transform: translate3D(10.4%, 25%, calc(var(--itemZ) * var(--cameraSpeed) * 853 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(854) { + transform: translate3D(10.9%, 159%, calc(var(--itemZ) * var(--cameraSpeed) * 854 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(855) { + transform: translate3D(1.9%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 855 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(856) { + transform: translate3D(5%, 224%, calc(var(--itemZ) * var(--cameraSpeed) * 856 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(857) { + transform: translate3D(1.5%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 857 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(858) { + transform: translate3D(15.6%, 50%, calc(var(--itemZ) * var(--cameraSpeed) * 858 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(859) { + transform: translate3D(8.3%, 285%, calc(var(--itemZ) * var(--cameraSpeed) * 859 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(860) { + transform: translate3D(15.2%, 243%, calc(var(--itemZ) * var(--cameraSpeed) * 860 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(861) { + transform: translate3D(9.1%, 290%, calc(var(--itemZ) * var(--cameraSpeed) * 861 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(862) { + transform: translate3D(19.6%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 862 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(863) { + transform: translate3D(1.1%, 38%, calc(var(--itemZ) * var(--cameraSpeed) * 863 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(864) { + transform: translate3D(11.7%, 136%, calc(var(--itemZ) * var(--cameraSpeed) * 864 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(865) { + transform: translate3D(6%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 865 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(866) { + transform: translate3D(6.5%, 16%, calc(var(--itemZ) * var(--cameraSpeed) * 866 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(867) { + transform: translate3D(5.6%, 277%, calc(var(--itemZ) * var(--cameraSpeed) * 867 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(868) { + transform: translate3D(1.6%, 239%, calc(var(--itemZ) * var(--cameraSpeed) * 868 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(869) { + transform: translate3D(5.7%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 869 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(870) { + transform: translate3D(3.1%, 124%, calc(var(--itemZ) * var(--cameraSpeed) * 870 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(871) { + transform: translate3D(1.8%, 30%, calc(var(--itemZ) * var(--cameraSpeed) * 871 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(872) { + transform: translate3D(9.6%, 95%, calc(var(--itemZ) * var(--cameraSpeed) * 872 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(873) { + transform: translate3D(13.8%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 873 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(874) { + transform: translate3D(1.7%, 142%, calc(var(--itemZ) * var(--cameraSpeed) * 874 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(875) { + transform: translate3D(6.9%, 42%, calc(var(--itemZ) * var(--cameraSpeed) * 875 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(876) { + transform: translate3D(2.4%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 876 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(877) { + transform: translate3D(6.4%, 78%, calc(var(--itemZ) * var(--cameraSpeed) * 877 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(878) { + transform: translate3D(9.6%, 22%, calc(var(--itemZ) * var(--cameraSpeed) * 878 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(879) { + transform: translate3D(4.1%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 879 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(880) { + transform: translate3D(5.1%, 151%, calc(var(--itemZ) * var(--cameraSpeed) * 880 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(881) { + transform: translate3D(14.5%, 167%, calc(var(--itemZ) * var(--cameraSpeed) * 881 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(882) { + transform: translate3D(5.4%, 49%, calc(var(--itemZ) * var(--cameraSpeed) * 882 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(883) { + transform: translate3D(3.1%, 155%, calc(var(--itemZ) * var(--cameraSpeed) * 883 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(884) { + transform: translate3D(2.5%, 84%, calc(var(--itemZ) * var(--cameraSpeed) * 884 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(885) { + transform: translate3D(10.6%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 885 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(886) { + transform: translate3D(0.5%, 222%, calc(var(--itemZ) * var(--cameraSpeed) * 886 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(887) { + transform: translate3D(9.8%, 209%, calc(var(--itemZ) * var(--cameraSpeed) * 887 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(888) { + transform: translate3D(9.5%, 202%, calc(var(--itemZ) * var(--cameraSpeed) * 888 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(889) { + transform: translate3D(7.6%, 122%, calc(var(--itemZ) * var(--cameraSpeed) * 889 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(890) { + transform: translate3D(0.4%, 43%, calc(var(--itemZ) * var(--cameraSpeed) * 890 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(891) { + transform: translate3D(1.7%, 299%, calc(var(--itemZ) * var(--cameraSpeed) * 891 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(892) { + transform: translate3D(16%, 64%, calc(var(--itemZ) * var(--cameraSpeed) * 892 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(893) { + transform: translate3D(18.2%, 184%, calc(var(--itemZ) * var(--cameraSpeed) * 893 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(894) { + transform: translate3D(15.4%, 195%, calc(var(--itemZ) * var(--cameraSpeed) * 894 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(895) { + transform: translate3D(19.1%, 227%, calc(var(--itemZ) * var(--cameraSpeed) * 895 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(896) { + transform: translate3D(9.8%, 137%, calc(var(--itemZ) * var(--cameraSpeed) * 896 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(897) { + transform: translate3D(0.7%, 102%, calc(var(--itemZ) * var(--cameraSpeed) * 897 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(898) { + transform: translate3D(10.4%, 51%, calc(var(--itemZ) * var(--cameraSpeed) * 898 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(899) { + transform: translate3D(11.6%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 899 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(900) { + transform: translate3D(7.2%, 169%, calc(var(--itemZ) * var(--cameraSpeed) * 900 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(901) { + transform: translate3D(8.6%, 40%, calc(var(--itemZ) * var(--cameraSpeed) * 901 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(902) { + transform: translate3D(7.3%, 143%, calc(var(--itemZ) * var(--cameraSpeed) * 902 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(903) { + transform: translate3D(15.9%, 196%, calc(var(--itemZ) * var(--cameraSpeed) * 903 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(904) { + transform: translate3D(16.1%, 124%, calc(var(--itemZ) * var(--cameraSpeed) * 904 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(905) { + transform: translate3D(13.8%, 68%, calc(var(--itemZ) * var(--cameraSpeed) * 905 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(906) { + transform: translate3D(7.5%, 200%, calc(var(--itemZ) * var(--cameraSpeed) * 906 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(907) { + transform: translate3D(14.5%, 80%, calc(var(--itemZ) * var(--cameraSpeed) * 907 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(908) { + transform: translate3D(14.1%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 908 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(909) { + transform: translate3D(14.2%, 273%, calc(var(--itemZ) * var(--cameraSpeed) * 909 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(910) { + transform: translate3D(7.8%, 9%, calc(var(--itemZ) * var(--cameraSpeed) * 910 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(911) { + transform: translate3D(1%, 244%, calc(var(--itemZ) * var(--cameraSpeed) * 911 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(912) { + transform: translate3D(4.9%, 144%, calc(var(--itemZ) * var(--cameraSpeed) * 912 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(913) { + transform: translate3D(18.5%, 272%, calc(var(--itemZ) * var(--cameraSpeed) * 913 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(914) { + transform: translate3D(3%, 136%, calc(var(--itemZ) * var(--cameraSpeed) * 914 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(915) { + transform: translate3D(6.6%, 72%, calc(var(--itemZ) * var(--cameraSpeed) * 915 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(916) { + transform: translate3D(6%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 916 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(917) { + transform: translate3D(10.7%, 218%, calc(var(--itemZ) * var(--cameraSpeed) * 917 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(918) { + transform: translate3D(4.9%, 226%, calc(var(--itemZ) * var(--cameraSpeed) * 918 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(919) { + transform: translate3D(15.4%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 919 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(920) { + transform: translate3D(14.4%, 82%, calc(var(--itemZ) * var(--cameraSpeed) * 920 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(921) { + transform: translate3D(3.8%, 264%, calc(var(--itemZ) * var(--cameraSpeed) * 921 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(922) { + transform: translate3D(18.2%, 51%, calc(var(--itemZ) * var(--cameraSpeed) * 922 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(923) { + transform: translate3D(10.6%, 14%, calc(var(--itemZ) * var(--cameraSpeed) * 923 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(924) { + transform: translate3D(3.3%, 183%, calc(var(--itemZ) * var(--cameraSpeed) * 924 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(925) { + transform: translate3D(4.6%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 925 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(926) { + transform: translate3D(12.7%, 282%, calc(var(--itemZ) * var(--cameraSpeed) * 926 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(927) { + transform: translate3D(0.1%, 139%, calc(var(--itemZ) * var(--cameraSpeed) * 927 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(928) { + transform: translate3D(15.1%, 71%, calc(var(--itemZ) * var(--cameraSpeed) * 928 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(929) { + transform: translate3D(10.8%, 95%, calc(var(--itemZ) * var(--cameraSpeed) * 929 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(930) { + transform: translate3D(17.4%, 214%, calc(var(--itemZ) * var(--cameraSpeed) * 930 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(931) { + transform: translate3D(10.5%, 58%, calc(var(--itemZ) * var(--cameraSpeed) * 931 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(932) { + transform: translate3D(7.9%, 265%, calc(var(--itemZ) * var(--cameraSpeed) * 932 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(933) { + transform: translate3D(5.6%, 207%, calc(var(--itemZ) * var(--cameraSpeed) * 933 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(934) { + transform: translate3D(0.1%, 93%, calc(var(--itemZ) * var(--cameraSpeed) * 934 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(935) { + transform: translate3D(12.2%, 89%, calc(var(--itemZ) * var(--cameraSpeed) * 935 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(936) { + transform: translate3D(11.3%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 936 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(937) { + transform: translate3D(17.5%, 223%, calc(var(--itemZ) * var(--cameraSpeed) * 937 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(938) { + transform: translate3D(10.4%, 193%, calc(var(--itemZ) * var(--cameraSpeed) * 938 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(939) { + transform: translate3D(9.9%, 50%, calc(var(--itemZ) * var(--cameraSpeed) * 939 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(940) { + transform: translate3D(16.8%, 117%, calc(var(--itemZ) * var(--cameraSpeed) * 940 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(941) { + transform: translate3D(13.4%, 73%, calc(var(--itemZ) * var(--cameraSpeed) * 941 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(942) { + transform: translate3D(13.1%, 114%, calc(var(--itemZ) * var(--cameraSpeed) * 942 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(943) { + transform: translate3D(18.1%, 292%, calc(var(--itemZ) * var(--cameraSpeed) * 943 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(944) { + transform: translate3D(8.6%, 112%, calc(var(--itemZ) * var(--cameraSpeed) * 944 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(945) { + transform: translate3D(4.1%, 53%, calc(var(--itemZ) * var(--cameraSpeed) * 945 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(946) { + transform: translate3D(10.9%, 54%, calc(var(--itemZ) * var(--cameraSpeed) * 946 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(947) { + transform: translate3D(8%, 5%, calc(var(--itemZ) * var(--cameraSpeed) * 947 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(948) { + transform: translate3D(19.1%, 153%, calc(var(--itemZ) * var(--cameraSpeed) * 948 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(949) { + transform: translate3D(15.5%, 286%, calc(var(--itemZ) * var(--cameraSpeed) * 949 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(950) { + transform: translate3D(1.5%, 260%, calc(var(--itemZ) * var(--cameraSpeed) * 950 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(951) { + transform: translate3D(18.7%, 43%, calc(var(--itemZ) * var(--cameraSpeed) * 951 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(952) { + transform: translate3D(19.5%, 187%, calc(var(--itemZ) * var(--cameraSpeed) * 952 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(953) { + transform: translate3D(9.6%, 287%, calc(var(--itemZ) * var(--cameraSpeed) * 953 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(954) { + transform: translate3D(18.3%, 7%, calc(var(--itemZ) * var(--cameraSpeed) * 954 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(955) { + transform: translate3D(8.3%, 28%, calc(var(--itemZ) * var(--cameraSpeed) * 955 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(956) { + transform: translate3D(5%, 65%, calc(var(--itemZ) * var(--cameraSpeed) * 956 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(957) { + transform: translate3D(13%, 18%, calc(var(--itemZ) * var(--cameraSpeed) * 957 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(958) { + transform: translate3D(9.7%, 201%, calc(var(--itemZ) * var(--cameraSpeed) * 958 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(959) { + transform: translate3D(15.3%, 21%, calc(var(--itemZ) * var(--cameraSpeed) * 959 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(960) { + transform: translate3D(19.6%, 38%, calc(var(--itemZ) * var(--cameraSpeed) * 960 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(961) { + transform: translate3D(13.3%, 247%, calc(var(--itemZ) * var(--cameraSpeed) * 961 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(962) { + transform: translate3D(15.9%, 240%, calc(var(--itemZ) * var(--cameraSpeed) * 962 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(963) { + transform: translate3D(10%, 7%, calc(var(--itemZ) * var(--cameraSpeed) * 963 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(964) { + transform: translate3D(4.9%, 154%, calc(var(--itemZ) * var(--cameraSpeed) * 964 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(965) { + transform: translate3D(16.5%, 9%, calc(var(--itemZ) * var(--cameraSpeed) * 965 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(966) { + transform: translate3D(9.3%, 191%, calc(var(--itemZ) * var(--cameraSpeed) * 966 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(967) { + transform: translate3D(6.2%, 20%, calc(var(--itemZ) * var(--cameraSpeed) * 967 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(968) { + transform: translate3D(5.3%, 256%, calc(var(--itemZ) * var(--cameraSpeed) * 968 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(969) { + transform: translate3D(18.6%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 969 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(970) { + transform: translate3D(12.7%, 23%, calc(var(--itemZ) * var(--cameraSpeed) * 970 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(971) { + transform: translate3D(12.7%, 106%, calc(var(--itemZ) * var(--cameraSpeed) * 971 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(972) { + transform: translate3D(14.5%, 210%, calc(var(--itemZ) * var(--cameraSpeed) * 972 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(973) { + transform: translate3D(6%, 239%, calc(var(--itemZ) * var(--cameraSpeed) * 973 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(974) { + transform: translate3D(13.7%, 169%, calc(var(--itemZ) * var(--cameraSpeed) * 974 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(975) { + transform: translate3D(2.3%, 135%, calc(var(--itemZ) * var(--cameraSpeed) * 975 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(976) { + transform: translate3D(14.7%, 229%, calc(var(--itemZ) * var(--cameraSpeed) * 976 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(977) { + transform: translate3D(11.5%, 164%, calc(var(--itemZ) * var(--cameraSpeed) * 977 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(978) { + transform: translate3D(18.7%, 233%, calc(var(--itemZ) * var(--cameraSpeed) * 978 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(979) { + transform: translate3D(18.6%, 101%, calc(var(--itemZ) * var(--cameraSpeed) * 979 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(980) { + transform: translate3D(11%, 223%, calc(var(--itemZ) * var(--cameraSpeed) * 980 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(981) { + transform: translate3D(6.5%, 255%, calc(var(--itemZ) * var(--cameraSpeed) * 981 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(982) { + transform: translate3D(1.7%, 108%, calc(var(--itemZ) * var(--cameraSpeed) * 982 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(983) { + transform: translate3D(9.6%, 190%, calc(var(--itemZ) * var(--cameraSpeed) * 983 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(984) { + transform: translate3D(16.5%, 122%, calc(var(--itemZ) * var(--cameraSpeed) * 984 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(985) { + transform: translate3D(1.4%, 208%, calc(var(--itemZ) * var(--cameraSpeed) * 985 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(986) { + transform: translate3D(4.4%, 225%, calc(var(--itemZ) * var(--cameraSpeed) * 986 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(987) { + transform: translate3D(15.1%, 290%, calc(var(--itemZ) * var(--cameraSpeed) * 987 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(988) { + transform: translate3D(1.4%, 187%, calc(var(--itemZ) * var(--cameraSpeed) * 988 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(989) { + transform: translate3D(2.4%, 258%, calc(var(--itemZ) * var(--cameraSpeed) * 989 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(990) { + transform: translate3D(15.3%, 29%, calc(var(--itemZ) * var(--cameraSpeed) * 990 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(991) { + transform: translate3D(14.8%, 279%, calc(var(--itemZ) * var(--cameraSpeed) * 991 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(992) { + transform: translate3D(0.5%, 29%, calc(var(--itemZ) * var(--cameraSpeed) * 992 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(993) { + transform: translate3D(3.4%, 15%, calc(var(--itemZ) * var(--cameraSpeed) * 993 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(994) { + transform: translate3D(7%, 10%, calc(var(--itemZ) * var(--cameraSpeed) * 994 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(995) { + transform: translate3D(19%, 42%, calc(var(--itemZ) * var(--cameraSpeed) * 995 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(996) { + transform: translate3D(3.2%, 218%, calc(var(--itemZ) * var(--cameraSpeed) * 996 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(997) { + transform: translate3D(8.6%, 55%, calc(var(--itemZ) * var(--cameraSpeed) * 997 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(998) { + transform: translate3D(5.8%, 59%, calc(var(--itemZ) * var(--cameraSpeed) * 998 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(999) { + transform: translate3D(9.8%, 224%, calc(var(--itemZ) * var(--cameraSpeed) * 999 * -.5px)); +} +.viewport .scene3D-container .scene3D > div:nth-child(1000) { + transform: translate3D(4.1%, 275%, calc(var(--itemZ) * var(--cameraSpeed) * 1000 * -.5px)); +} + +@font-face { + font-family: "Cotham"; + src: url("/assets/fonts/CothamSans.otf"); +} +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: "Cotham"; + background-color: #ffffff; + background-color: rgba(0, 0, 0, 0.17); + background-color: black; + color: hsl(231deg, 15%, 18%); + padding: 0; + margin: 0; +} + +#loading { + width: 100%; + height: 100%; + position: absolute; + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +#text { + position: fixed; + z-index: 100; + left: 0; + bottom: 0; + width: 150%; + display: flex; +} + +.marquee { + font-size: 40px; + font-family: sans-serif; + color: #0f0; + white-space: nowrap; + animation: marquee 50s infinite linear; +} + +@keyframes marquee { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-50%); + } +} +span { + position: relative; + color: black; + color: #0f0; + font-family: "Courier New", Courier, monospace; + font-size: 20px; +} + +@media only screen and (min-width: 600px) { + .scene3D h1 { + font-size: 9vw; + } + .scene3D p { + font-size: 7vw; + } + .scene3D img { + width: 230vw; + } +} +.scene3D > div { + padding: 5vw; +} +.scene3D > div h1 { + font-size: 6vw; +} +.scene3D > div p, +.scene3D > div a, +.scene3D > div li { + font-size: 5vw; +} +.scene3D > div img { + width: 150vw; +} +.scene3D > div a { + text-decoration: underline; + color: #ffffff; + font-size: 5vw; +} +.scene3D > div a:hover { + text-decoration: none; +} + +/*# sourceMappingURL=style.css.map */ diff --git a/axios-example/static/style.css.map b/axios-example/static/style.css.map new file mode 100644 index 0000000..42bc84a --- /dev/null +++ b/axios-example/static/style.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAKA;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;AADJ;EACI;;;AAoDxB;EACI;EACA;;AAWJ;AAAA;AAAA;EAGI;;;AAGJ;EACI;;;AAGJ;EACI;EACA,kBAnBK;EAoBL;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACI;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;IACI;;EAGJ;IACI;;;AAKR;EACI;EACA;EACA;EACA;EACA;;;AASA;EACI;IACI,WA7EH;;EAgFD;IACI,WAlFH;;EAqFD;IACI;;;AAIR;EACI;;AAIA;EACI,WAjGN;;AAoGE;AAAA;AAAA;EAGI,WAxGN;;AA2GE;EACI;;AAGJ;EACI;EACA,OAnHH;EAoHG,WAlHN;;AAqHE;EACI","file":"style.css"} \ No newline at end of file diff --git a/axios-example/static/style.scss b/axios-example/static/style.scss new file mode 100755 index 0000000..c0b4cdc --- /dev/null +++ b/axios-example/static/style.scss @@ -0,0 +1,240 @@ +:root { + --scenePerspective: 1; + --scenePerspectiveOriginX: 50; + --scenePerspectiveOriginY: 0; + --itemZ: 2; + --cameraSpeed: 20; // Where 1 is the fastest + --cameraZ: 0; + --viewportHeight: 105; +} + +$n : 1000; + + +.viewport { + height: calc(var(--viewportHeight) * 1px); + + .scene3D-container { + z-index: 1; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + perspective: calc(var(--scenePerspective) * var(--cameraSpeed) * 1px); + perspective-origin: calc(var(--scenePerspectiveOriginX) * 1%) calc(var(--scenePerspectiveOriginY) * 1%); + will-change: perspective-origin; + transform: translate3d(0, 0, 0); //Allow Hardware-Accelerated CSS + + .scene3D { + position: absolute; + top: 0; + height: 100vh; + width: 100%; + transform-style: preserve-3d; + transform: translateZ(calc(var(--cameraZ) * 1px)); + will-change: transform; + // transform: rotateX(20deg); + + >div { + position: absolute; + display: block; + width: 70%; + top: 100%; + + &:nth-child(2n) { + left: 80%; + bottom: 10%; + } + + &:nth-child(2n + 1) { + right: 80%; + bottom: 10% + } + + + @for $i from 0 through $n { + &:nth-child(#{$i}) { + transform: translate3D(random(200) * .1%, random(300) * 1%, calc(var(--itemZ) * var(--cameraSpeed) * #{$i} * -.5px)); + // transform: translate3D(15.4%, 250%s, calc(var(--itemZ) * var(--cameraSpeed) * 1 * -.5px)); + + } + } + } + } + + + // >div { + // position: absolute; + // display: block; + // width: 100%; + // top: 70%; + + // @media only screen and (min-width: 600px) { + // width: 100%; + // } + + // @media only screen and (max-width: 600px) { + // width: 100%; + // } + + // &:nth-child(2n) { + // left: 0; + // } + + // &:nth-child(2n + 1) { + // right: 0; + // } + + // @for $i from 0 through $n { + // &:nth-child(#{$i}) { + // transform: translate3D(random(50) - 25 * 1%, random(100) - 50 * 1%, calc(var(--itemZ) * var(--cameraSpeed) * #{$i} * -1px)); + // } + // } + + // @media only screen and (max-width: 600px) { + // @for $i from 0 through 20 { + // &:nth-child(#{$i}) { + // transform: translate3D(1%, -80%, calc(var(--itemZ) * var(--cameraSpeed) * #{$i} * -1px)); + // } + // } + // } + // } + // } + } +} + +// ---------- +// Styling +// ---------- +@font-face { + font-family: "Cotham"; + src: url("/assets/fonts/CothamSans.otf"); +} + +$main: #0f0; +$second: #ffffff; +$third: #000; +$reg: 5vw; +$tit: 6vw; +$regRes: 7vw; +$titRes: 9vw; + +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: "Cotham"; + background-color: $second; + background-color: rgba(0, 0, 0, 0.17); + background-color: black; + color: hsl(231, 15%, 18%); + padding: 0; + margin: 0; +} + +#loading { + width: 100%; + height: 100%; + position: absolute; + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + + +#text { + position: fixed; + z-index: 100; + left: 0; + bottom: 0; + width: 150%; + display: flex; +} + +.marquee { + font-size: 40px; + font-family: sans-serif; + color: #0f0; + white-space: nowrap; + animation: marquee 50s infinite linear; +} + +@keyframes marquee { + 0% { + transform: translateX(0) + } + + 100% { + transform: translateX(-50%) + } +} + + +span { + position: relative; + color: black; + color: #0f0; + font-family: 'Courier New', Courier, monospace; + font-size: 20px; + // white-space: nowrap; + +} + + + + +.scene3D { + @media only screen and (min-width: 600px) { + h1 { + font-size: $titRes; + } + + p { + font-size: $regRes; + } + + img { + width: 230vw; + } + } + + >div { + padding: 5vw; + + // background-color: $second; + // border: solid $main .3vw; + h1 { + font-size: $tit; + } + + p, + a, + li { + font-size: $reg; + } + + img { + width: 150vw; + } + + a { + text-decoration: underline; + color: $second; + font-size: $reg; + } + + a:hover { + text-decoration: none; + // filter: invert(100%); + } + } +} \ No newline at end of file diff --git a/axios-example/templates/index.html b/axios-example/templates/index.html new file mode 100644 index 0000000..bc14246 --- /dev/null +++ b/axios-example/templates/index.html @@ -0,0 +1,190 @@ + + + + + + + + + + + + Harvesting the Net + + + + + + + +
    +

    + +

    +
    + + +
    +
    +
    + +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/meta.json b/meta.json new file mode 100644 index 0000000..cb2be17 --- /dev/null +++ b/meta.json @@ -0,0 +1 @@ +{"0": "View Vaast Colson's artworks on artnet. Learn about the artist and find an in-depth biography, exhibitions, original artworks, the latest news, ...", "1": "Stay up to date with Vaast Colson (Belgian, 1977), APT artist. Discover works for sale, auction results, market data, news and exhibitions on MutualArt.", "2": "Biography Vaast Colson (Kapellen, Belgium, 1977) Lives and works in Antwerp, Belgium. Monopolis \u2014 Antwerp. 10 September \u2014 6 November 2005. Exhibition.", "3": "Vaast Colson (\u00b01977, Belgium) Vaast Colson's artworks are essentially ludic models of social spaces. His projects place the spectators into a certain social ...", "4": "Browse the latest artworks, exhibitions, shows by Vaast Colson. On Artland you can find art for sale, browse 3D gallery exhibitions and much more.", "5": "Vaast Colson MAES & MATTHYS GALLERY Antwerp. 29. Nov 22. Feb 2009. Un-Scene WIELS Contemporary Art Centre, Brussels. 19. Oct 04. Jan 2009.", "6": "Vaast Colson and Kati Heck \u201cShow me yours & I'll show you mine\u201d at Museum of Contemporary Art Antwerp. 15.05.2016. Reading Time 2\u2032. Share.", "7": "Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.", "8": "The artist Vaast Colson is ranked among the Top 10000 on ArtFacts. Find out more...", "9": "Vaast Colson about his drawing activities, on the occasion of The Big Draw in Antwerp. www.thebigdraw.be Sine Van Menxel's solo exhibition, Fencing a...", "10": "'Liberatomania': new project by Vaast Colson for Independent Brussels, in collaboration with trampoline, Antwerp: don't miss it!...", "11": "vaast.colson@ap.be. Ambitious, passionate, genuine, respectful and open, these are the values with which the university meets the world. More about AP ...", "12": "Tags archives: vaast-colson. Barocchi. Sanguine. Luc Tuymans on Baroque \u00b7 ATP DIARY \u00b7 2 Minutes \u00b7 Talks \u00b7 Art Text \u00b7 Artist's Diary \u00b7 Colophon \u00b7 Contact ...", "13": "About Vaast Colsen: Colson (1977, Belgium) lives and works in Antwerp, Belgium. He attained his MA of Arts degree in Painting at the Royal Academy of ...", "14": "Winner of the BCC (Brussels Cologne Contemporaries) Award, Vaast COLSON presents an installation that, as is customary, reflects an unbridled subjectivity ...", "15": "Artist page in the MACBA Collection of Vaast Colson. ... Vaast Colson. Print file. Share. Related. Related Archive documents. Archive document. Ricoh book.", "16": "Vaast Colson: \u00b7 \"N 50\u00b053'41,47\u201d\u2013 E 4\u00b020'29,48\u201d\" \u00b7 \"You used to be part of something (public poster edition)\" \u00b7 \"SIZING & RESIZING - All sound intentions and then ...", "17": "w_wh_at . 21 augustus 2020. The artist chose to quote a number of Instagram Posts from the voorforvaast fanclub. The members of vfvf publish excerpts from their ...", "18": "Kunsthuis Yellowart - curator Vaast Colson. \u201cIk stel me graag voor dat het werkwoord cureren zijn/haar oorsprong vindt in het Latijnse 'curare' wat 'zorgen' ...", "19": "Milan, Galerie Zonca & Zonca, Vaast Colson. Illuminanti Icone Tratte dal Lavoro del Giovane Maestro Fiammingo, 2006. Special notice.", "20": "Vaast Colson. Webring. Arte.Go.it \u00b7 Arte.Go.Shop \u00b7 dgPixel Multimedia \u00b7 TechShop \u00b7 TechBlog \u00b7 Redazione Cultura \u00b7 WordPress Area Test", "21": "Include out of stock items. Vaast Colson. Gagarin. Raymond Pettibon, Mekhitar Garabedian, Abraham Cruzvillegas, Fabienne Aud\u00e9oud, Vaast Colson, ...", "22": "Vaast Colson, Luc Matthys, Christine Vuegen ... Colson's artistic practice leaves ample room for the cross-pollinating potential of collaboration and the ...", "23": "Vent'anni di UnDo.Net, un'opera d'arte ideata da artisti che hanno coinvolto centinaia di altri autori e operatori nella costruzione di un ecosistema, di un ...", "24": "Explore releases from Vaast Colson at Discogs. Shop for Vinyl, CDs and more from Vaast Colson at the Discogs Marketplace.", "25": "35 Likes, 0 Comments - Mathieu Van Damme (@mathieu_toykyo) on Instagram: \u201cVaast Colson #muhka #vaastcolson #antwerp\u201d", "26": "artist, Figure 87: Vaast Colson. term, eternal network / la f\u00eate permanente. year, 2016. courtesy of, Courtesy of the artist \u00a9 M HKA.", "27": "Vaast Colson. Save. Cancel. Delete. Events \u00b7 Edit \u00b7 Unresolved. 25 Jun - 06 Nov 2016. De Appel, Amsterdam \u00b7 The Image Generator. 29 Jan - 01 Feb 2015.", "28": "Vaast Colson is an artist who constantly questions the relationship with the audience. He haa a strong interest in mythology and the traditional mystique of ...", "29": "... E'wao Kagoshima, Vittorio Brodmann, Mirak Jamal, Olivier Millagou, Sally Ross, Kaido Ole, Vaast Colson, Liz Craft, Ulrich Wulff, Alex Morrison.", "30": "27-apr-2016 - Deze pin is ontdekt door Magda. Ontdek (en bewaar!) je eigen pins op Pinterest.", "31": "Vaast Colson. Cover art. How to Gather: Acting Relations, Mapping Positions \u00b7 Bart De Baere, Defne Ayas, Nicolaus Schafhausen, et al.", "32": "In Bornem (her)opende ze met huiskunstenaar Vaast Colson, en die keuze had niet beter kunnen zijn. Colson is immers een kunstenaar die tegen de ...", "33": "Ten lies Vaast Colson told as a child were printed on 500 white balloons. Each balloon is accompanied by a mini-disc on which Colson explains the project and a ...", "34": "Vaast Colson. Position. Teaching staff. Email address. vaast.colson@ap.be. Departement. Royal Academy of Fine Arts Antwerp. Mutsaardstraat 31,", "35": "Apr 13, 2022 \u2014 Kunstenaar Vaast Colson, die tot 1998 in Merksplas woonde, neemt er enkele maanden zijn intrek. Het Frans Masereel Centrum groeide door de ...", "36": "AbeBooks.com: Vaast Colson : Still some cream on the screen / Kati Heck : Holy Hauruck: Text: EN/NL. Unp.; ill.; 20 x 26,5 cm; 500 g. Light shelfwear.", "37": "Marc Nagtzaam \u00b7 Fabienne Aud\u00e9oud \u00b7 Christine Meisner \u00b7 Vaast Colson \u00b7 Mekhitar Garabedian \u00b7 Raymond Pettibon \u00b7 Javier T\u00e9llez \u00b7 Abraham Cruzvillegas.", "38": "IAC \u2014 Institut d'art contemporain \u2014 Villeurbanne/Rh\u00f4ne-Alpes.", "39": "Vaast Colson. Sculpture , Variable dimensions. Concrete, plastic, metal, LED. In Vaast Colson's opinion, a piece of art is not a finished product but part ...", "40": "Want ja, ook kunst is rock 'n roll. En ook kunstenaars hebben fanclubs. M HKA nodigde vf vf uit, de fanclub van beeldend kunstenaar Vaast Colson.", "41": "Oct 4, 2021 \u2014 Vaast Colson is een artistieke duizendpoot die zich als kunstenaar bewust op het snijvlak van kunst en maatschappij begeeft.", "42": "Consult contact data, management and key figures for VAAST COLSON FOUNDATION (0892.660.019) from Antwerpen (2018) and other companies in sector Art, ...", "43": "een openhartig gesprek met Vaast Colson\". A sudden temporary vastly increased release of serotonin in the synaptic cleft, \u2026 a frank conversation with Vaast ...", "44": "Vaast Colson. Done. Show your appreciation with the gift of Flickr Pro. Comment. 117 views. 0 faves. 0 comments. Taken on April 14, 2012.", "45": "Vaast Colson \u00b7 Momenteel hebben we geen werken van Vaast Colson in onze collectie. Contacteer de galerie om kunstwerken van deze kunstenaar te bekijken. \u00b7 Schrijf ...", "46": "FINISSAGE / Performatik: Messieurs Delmotte - Vaast Colson - Dennis Tyfus. Vernissage. Performances. 22 02 2009 00:00 01:00.", "47": "Vaast Colson (b. 1977, lives and works in Antwerp) is bluffing. He has no choice, because as a young artist he is not yet on solid ground, does not have a ...", "48": "Vaast Colson containers and acoustics. Vaast Colson. CONTAINERS & ACOUSTICS. We're in it together, you're in it alone. 2014. Exhibition view.", "49": "Apr 19, 2009 \u2014 In Italiano > Related article Vaast Colson (1977) is an artist who teaches at Antwerp Royal Academy of Fine Arts. He's one of the ...", "50": "In zijn werk buigt Vaast Colson zich over het ontstaan van het beeld, de methodiek van de beeldende taal. De voorwerpen, materialen, beelden, texturen, ...", "51": "Vaast Colson 99/09 (Hardcover). Deze eerste monografie biedt een overzicht van het werk van Belgisch kunstenaar Vaast Colson en omvat een periode van...", "52": "Oct 7, 2020 \u2014 Deze keer kijken we naar een sculptuur van Vaast Colson. Graag vertel ik hier iets meer over The Helena Sculpture (2004-2007) van Vaast Colson ( ...", "53": "Vaast Colson nam deel aan de tentoonstelling Positie kiezen met enkele minieme, precieze interventies. De tekst in de bezoekersgids luidde als volgt: \"En ...", "54": "In 2001 galoppeerde Vaast Colson (\u00b01977) als de nobele ridder Widu Gasti de Belgische hedendaagse kunstwereld binnen. Zijn eerste solotentoonstelling zette ...", "55": "Vaast Colson. museum notebook. Hardcover | Nederlands. \u20ac 7,50. + 15 punten. Verwachte leverdatum onbekend. In winkelmandje. Eenvoudig bestellen.", "56": "[Vaast Colson] Van zaterdag 14 januari 2023 tot en met zondag 26 maart 2023 Open elke vrijdag, zaterdag en zondag van 10u00 tot 17u00. Lees meer ...", "57": "Vaast Colson. Schwarzer Peter \u2014 das Original. 20.12.2019 \u2014 21.12.2019. Presentatie van de editie: VAAST COLSON, \u201c ...", "58": "May 15, 2015 \u2014 Vaast Colson - de kunstenaar met de mooiste naam, ever - zette donderdagavond 14 mei de toon met een vrijmoedig, inspirerend en aangenaam ...", "59": "Aug 25, 2013 \u2014 Inside Colson's 'vault' you'll also find a desk with an acryl plate engraving \u2013 the synthesis of the 12 portraits \u2013 at which you can sit to make ...", "60": "Name: VAAST COLSON FOUNDATION. Commercial name. Abbreviation. VAT: BE0892660019. Juridical form: Private stichting. Start date: 2007-10-01. Status: Actief.", "61": "Consultez les coordonn\u00e9es, dirigeants et chiffres-cl\u00e9s de VAAST COLSON FOUNDATION (0892.660.019) \u00e0 Antwerpen (2018) et d'autres soci\u00e9t\u00e9s du secteur Art, ...", "62": "Recyclart et JAP s'associent une fois de plus, \u00e0 Chapelle cette fois, et pr\u00e9sentent ensemble une exposition de l'artiste Vaast Colson.", "63": "Colson, Vaast(1977 -) ... Bornem : Maes & Matthys Gallery, 2015. ... All rights to the name International Foundation for Art Research (IFAR\u00ae) are reserved by the ...", "64": "Drop by on 3 December for an artist talk with Vaast Colson. With works by Aur\u00e9lie Bayad \u2013 Oona Bovri \u2013 Vaast Colson \u2013 Marijke De Roover \u2013 Messieurs Delmotte \u2013 ...", "65": "Oct 20, 2019 \u2014 Vaast Colson (42), de action man van de conceptuele kunst, en Nel Aerts (32), de jonge blonde godin van de schilderkunst, zijn al bijna tien ...", "66": "PXL-MAD: Lezing Vaast Colson. 26/03/2015. CIAP, Lombaardstraat 23, Hasselt. De docenten van PXL-MAD, Vrije kunsten hebben ook dit academiejaar weer een ...", "67": "Vaast Colson [1] is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van Antwerpen.[2].", "68": "Maes & Matthys Gallery. Vaast Colson 99/09. Vaast Colson 99/09. Vaast Colson 99/09. Library Material \u2013 on artist. Maes & Matthys Gallery, 2009.", "69": "VAAST COLSON. Samenwerken met erkende kunstenaars is een cruciaal gegeven in de werking. van Kunsthuis Yellow Art. Gedurende twee jaren werden er samen met.", "70": "CIAP is een centrum voor actuele kunst gevestigd in Hasselt, Belgi\u00eb.", "71": "Sep 12, 2022 \u2014 Bid now on Invaluable: VAAST COLSON (\u00b01977) from Bernaerts Auctioneers on December 4, 0122 2:00 PM CET.", "72": "Vaast Colson is auteur, bekend van Containers & Acoustics (2015), Still some cream on the screen - Holy Hauruck (2016) en Vaast Colson 10/14 (2014).", "73": "2016 Rollende Koppen II (with Vaast Colson), Vansteensel & De Caigny Gallery, Antwerp (BE) 2016 New Wave Copy Centre (with Milan W. and DJ Moonchild), ...", "74": "Jun 27, 2015 \u2014 Vaast Colson (1977) speelt ook het spel van toevallige normering. Alleen lijkt het hier een stuk grappiger dan in de kranten.", "75": "Mar 24, 2012 \u2014 Interview met Vaast Colson, Antwerpen, zondag 18 maart 2012. Hilde Van Canneyt: Hallo Vaast, ik las dat je genoemd bent naar een econoom, ...", "76": "Vaast Colson (Kapellen, 1977) is a Belgian painter. He studied painting at the Royal Academy of Fine Arts in Antwerp. Colson's work is characterized by an ...", "77": "Jun 27, 2015 \u2014 Jeroen van der Hulst is onze nieuwste redacteur! Hij is schrijver en kunstenaar en werkt, na een tijd in Berlijn als organisator voor Agora ...", "78": "Vaast Colson, Dennis Tyfus en Peter Fengler gaan tijdens het Letterenhuisfestival in galerie Pinkie Bowtie op zoek naar de plaats van tekst en taal binnen ...", "79": "Feb 27, 2016 \u2014 Kati Heck & Vaast Colson ... Onder de titel Show me yours & I'll show you mine presenteert het Muhka solotentoonstellingen van twee Antwerpse ...", "80": "Sep 24, 2009 \u2014 Lees in de nieuwe METROPOLIS M Nr 4/2009 het uitgebreide artikel over de Vlaamse kunstenaars Vaast Colson en Dennis Tyfus.", "81": "Vaast Colson. Agenda \u00b7 20 jaar Ultra Eczema \u00b7 SUPERTIP: Dennis Tyfus viert in het weekend van 24-26 november het twintigjarig bestaan van zijn label ...", "82": "Vaast Colson. Artista. Naci\u00f3 en 1977 en Kapellen, Antwerpen, B\u00e9lgica. Reside en B\u00e9lgica.", "83": "Apr 3, 2018 \u2014 Vaast Colson (Kapellen, 1977) is een Belgisch kunstschilder. Hij studeerde schilderkunst aan de Koninklijke Academie voor Schone Kunsten van ...", "84": "Colson, Vaast. Author(s): Title: Publication year: Publication place: Publisher: Edition: Pages: Dimensions: Binding: Specifications:", "85": "Vaast Colson runs his own fan club from the castle as a true modern- day knight. Pictured is Fabian. M\u00e9relle's \"Chevalier\". Other works from the collection.", "86": "Feb 19, 2016 \u2014 Vaast Colson (Kapellen, 1977 \u2013 woont en werkt in Antwerpen) staat bekend om zijn veelzijdig beeldend werk dat sculpturen, installaties, ..."} \ No newline at end of file diff --git a/pics.json b/pics.json new file mode 100644 index 0000000..0c8ebb8 --- /dev/null +++ b/pics.json @@ -0,0 +1 @@ +{"0": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQl_ib6AHiQb7vkdQBZ9iUDZeD5kVMctd7NOA&usqp=CAU", "1": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqBbc2P0pyQW5diec1nu-sWqlPvbDUcIt_OA&usqp=CAU", "2": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLvOk39BlgcvhzIPMxNI4Ua8fO7rORj5QayA&usqp=CAU", "3": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR-SYbWWFRmARs-14KnV5T_mN9xcNuAYzTpPA&usqp=CAU", "4": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRDPJaJ1nIQAGNIopD-HjsmVy9KahcOvg-oCQ&usqp=CAU", "5": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT9kJVVKQZhSx3Qy6fZ4-NYnKTV99C-fKhhKw&usqp=CAU", "6": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQfawalAShyypGAsO-S0ZPX0MVz3gilhS094Q&usqp=CAU", "7": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSasNqfx8g_-ED7RJ2Iwlwktk3l3bl5fmAZ-w&usqp=CAU", "8": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRB17dIlgEdNVsMlqgNdFbs-yXhEx9fue2Kxg&usqp=CAU", "9": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUKFZHSy94mzLoz_viHIGwprZGj2_z5grycA&usqp=CAU", "10": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSydvup97dUZN5YWXYvkZ44QKezVmd9gvf1sA&usqp=CAU", "11": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdOp4HKY-OGwacua9pYPgwC5le4IWj5NKVXg&usqp=CAU", "12": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNEbssZH9M9Z6KFnuPTeF7QEB20oarKgVbog&usqp=CAU", "13": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8UdswoG_iE_se_6sXP-W-W4vuTf7l33YIvw&usqp=CAU", "14": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZqbzo8BzUgs6cwViiLsd8rW5XJifwsx-unA&usqp=CAU", "15": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwj2ubqDCWMQZO8BoXI8Fi-EP55eETPkBnnw&usqp=CAU", "16": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjoUAWfzImGrlkvrDzzwLHxpDOvkSXTk8RSA&usqp=CAU", "17": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSIaPP90Ci2MhSo9t7WCbIzPEDUes5T05oZmA&usqp=CAU", "18": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaFtprJMViJ3YPcNMbHEAYGd583hc0WI87Vw&usqp=CAU", "19": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQioW0TyTNr_OIt0kHzffsPwGsC50yoo2GOMg&usqp=CAU", "20": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQS8PqSywS1bB7nYBRp3p71ylGE2IH4F2mBhw&usqp=CAU", "21": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPMrN8JaJsb-6XTohscwaXoikn_Ys_VnWPtg&usqp=CAU", "22": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkG_izkc0CpL0PqjYQSkb2UN6kvt_KDVCG9g&usqp=CAU", "23": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKj2OhPuC_BQKb5Dql64mqPfJZDzgwoUu7Bg&usqp=CAU", "24": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3uX4qd_ynA8B9ADs8mJY3yEUec40wcyyRqA&usqp=CAU", "25": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqMwnwNOjZoy7BQkdjzvttWNFIOP45wlz9vw&usqp=CAU", "26": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZakjdVV0it1DHgTOHTifSNkqHm44B_eo0dw&usqp=CAU", "27": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSauJslhqnzNBBe4x-ejOq_E3Ur6DjBNTxoSA&usqp=CAU", "28": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfGlCrrYvJykKux1WjoJFMNSMKfoPtwf_S0g&usqp=CAU", "29": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgQrfB_HbvhLjSsh66S5vmuRpTLcnvwhQuKA&usqp=CAU", "30": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRtMkKA4TdzrjhZ0IfekAsCbivT-KeI5MxzQA&usqp=CAU", "31": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcStjZCeQvr-RKZOEUYb07cnIBT2TU864PmmNw&usqp=CAU", "32": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPgrpGL4FDASAHwJV_LYRY46ZJCxaWOVjGWw&usqp=CAU", "33": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqhqp_ApZj3XGtlovlk1SYrTSQH1eJv_mftA&usqp=CAU", "34": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAyq4PJzYKby9K4IQkSzgEBDeU6rahex6Oww&usqp=CAU", "35": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ7Z0W2HKV_7u5jDkKs3AuueeCshvcluF4mbw&usqp=CAU", "36": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEZssIZHIP46o6B3OHr-DJ5ntoxtZh0RVi9A&usqp=CAU", "37": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRZrbOEKq6oHVtRQxrsASrGHX7jU4ngQocZTQ&usqp=CAU", "38": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQMrnRkKCYbemI0fdVj2I8kARudAFwSiGVHw&usqp=CAU", "39": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTCIaOyt1Kd1NW0cYDLf7h_pNEf_XHlmDhMgA&usqp=CAU", "40": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTHH4VPTvV_QD56Rtu4pf9INQv7B3hHqMNzJg&usqp=CAU", "41": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrm3F11VH7Bd3SZCti-dBGKf_Zd-S4gfzWAQ&usqp=CAU", "42": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTri6cSGzV6HkW92Ov3EymUxX68kPjFabasOA&usqp=CAU", "43": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvuRpFrKbSAWFX1G8vL4tQQP32L35V_8rI5A&usqp=CAU", "44": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxDsjJsdNhsuODi1ZW8qv9flEAUwPSU7Jd9g&usqp=CAU", "45": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThH_4tlyq3SkILHbuyhsYFI922VK__rUFvTg&usqp=CAU", "46": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSv7BjsDz8m4S4IfeSh_wUiQRaI-173-XQ9jA&usqp=CAU", "47": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgYHblLR4oqQsOXgwND9agpkB-hAfTPXGjtA&usqp=CAU", "48": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSGcRPBPiONWQENsS1JZrVcq0wOz_z7UR1OA&usqp=CAU", "49": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSil_oO-mvqwMUvBdiP-xPin0F3UlUMiTBXCQ&usqp=CAU", "50": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYgUnwAyfZFPs1Wyg3Jubz_iflH7POohu5SA&usqp=CAU", "51": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiV4sOHOGgGi2xmWc7mOwRu3JSbNnVss7zw&usqp=CAU", "52": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZtNwo9JNjMX-ivWqk6besrc97XYDz9sp02Q&usqp=CAU", "53": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMlo4GMeVM8iyjRjhgyhXwN11ER9XfIFTOTA&usqp=CAU", "54": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9w20GRm5pfY8lNlNA1kSOC1493Cnocaae3w&usqp=CAU", "55": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTipa6DwdTck4xt_MuqCIoKwkB2na2ndtgwoA&usqp=CAU", "56": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTgOrglObIkFQtjeSwreH0PtEUpZvMV6Zibrg&usqp=CAU", "57": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQcRodjJzh2P7AzhA1UMp8x3nfoCMiiDDDO4Q&usqp=CAU", "58": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRTozLQXrYMEYn3FJ0cGDVxUs-UtNbO5Ah41w&usqp=CAU", "59": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFo5jOsLDIHYxUrLhCXropSukop7nTRHozxA&usqp=CAU", "60": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRk1ETGYUrvRspMwGwIZRh2jT5pAg5w-YX50Q&usqp=CAU", "61": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT63NQ9bSD_3zCNFuKGwPty27G0IcmF8w4KUA&usqp=CAU", "62": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3ttImHOxUhPG2G6whXQyoSOH6HhKDzDhljw&usqp=CAU", "63": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQamikTkkGeKWFmHmfsceg4b_YQNpImXLqD9Q&usqp=CAU", "64": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-thnIzZ4SE5soPu6O0f5o-QklwV-9mCKlQ&usqp=CAU", "65": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRzPHWLsWlfXDugsdRe67Bl_By5GB66glR4CA&usqp=CAU", "66": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTMbvHRJmh6FJZA7znoX9kzWmyiSuSqs3BJ9Q&usqp=CAU", "67": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-hKQ3zPxiqfVoCbKwn66H-b_q0n5c8y8W6A&usqp=CAU", "68": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcMeoqfUT5nOom5RJr-qMvYfwUKTkqSLjN4w&usqp=CAU", "69": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXJ_zFczQZWAHllshD0T2eOfH8F7zoiOkWUw&usqp=CAU", "70": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRED4OSHtwT8LB1BtyLnmxZc_QP3CehhjUg9g&usqp=CAU", "71": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTrL6Uf5-dmFpvkrW2-WJazoqo3SefcU9IqLw&usqp=CAU", "72": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaRhZVeVp5PIzyFVxU0Xr7c6pd93Ji8o2j2Q&usqp=CAU", "73": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6pIiAkF7dvC-iP87J-ShQNbg2_NX50yIkVQ&usqp=CAU", "74": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRudQLyifRdmTBmNj8HuV7udEi3FLkGcJ2GMg&usqp=CAU", "75": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQf-0rhTcLFnwcpVFNCxtwUurk4pqKX8PWDXQ&usqp=CAU", "76": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK2ZUyKDWvtO_5qOMHe6ua4869J5OLn-4yQw&usqp=CAU", "77": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8RPEakZXFwiqEjIbGYG8l65lGaMlHrKamew&usqp=CAU", "78": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU", "79": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRR_4FBqcyRhFQpTZTKcEznIDpiQ2N142gYCw&usqp=CAU", "80": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFOEvd24vMX707sqWK91s2rZuMPUAdS62Pr7M73gphp2o7BKZtGKvlIP_kkzwDELP9zGE&usqp=CAU", "81": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTBcVCzgnEnQdeQaM057Wcz_YVvCMccL69JNA&usqp=CAU", "82": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRR_4FBqcyRhFQpTZTKcEznIDpiQ2N142gYCw&usqp=CAU", "83": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFOEvd24vMX707sqWK91s2rZuMPUAdS62Pr7M73gphp2o7BKZtGKvlIP_kkzwDELP9zGE&usqp=CAU", "84": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSI7WkpI7XOe7OLgpSYxSxZUNkjjqw9myp_lznG0vGoPCPk_u31MUu46cL5EF1dFh0nxFk&usqp=CAU", "85": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkrZ9hXY50BcluytHRQzIKZmLNhvCC-xyYBc4e7SenmFrwIGEPbjhck7i1FrDVWlT993c&usqp=CAU", "86": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRqgo1DsADmzyZ2WnQ13ETdSlPledS5VflmV7hR4iuO8fY2v-B24tivYJqkNZcoJ42ereo&usqp=CAU", "87": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRny43WofbHnNhpGp9j-aZzFmmfCxjRvq6HtfJfFWvZRKjyuXk4LCYl5D3uk-eCeTtuzqQ&usqp=CAU", "88": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRhRGcvKQ82X1d9_WLQw8k4Jrh11QLgF8i2KOQz57eeEbCK58fzz0MFYlWARSONrL39Ag&usqp=CAU", "89": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS0HypeWCAhPpFAbJ84uekit5FkIYinovWB2ynwaXFRcEGDRMhJTfomS0yNFZqQxxlnsc4&usqp=CAU", "90": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQESxXhhB7MVuxNPCnWD_X6mgqBMMpqaUiq2RVgrQ_u4QyZ-Zv6-KzSfKBoWtT_1Zn3M5A&usqp=CAU", "91": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRrv7ujmQVAYaDG9j9SZA4ArhDKFs4LRKObtlo0pO-w0pM1cf4qp9T4ausA1BFGOg4YwZg&usqp=CAU", "92": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ4M6NJP-9EQduJ84NsKfiCTumjyG5o_AdLrwPn0d3ng0-ZtZTwwSQtBU6Bok9ClL81JbM&usqp=CAU", "93": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJZdlR9pbrQ9NcNGZ3kSocsaHSFtIKZTobyufHH2jymgajlzrL6et7gNKypb3_Fnf1RIo&usqp=CAU", "94": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT1S7tuE1msU5c4HZV55EXsHodIbUpoqf5fj-GS-fHef5zkYtpVb8uMHIi4mpqA6iCCMq4&usqp=CAU", "95": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkgJtmW0LhVSw122K25B7OTKUYETaSgE-WKdeOyWVL5qNwUw9DaI47VVYv9MkEk5Z9L9c&usqp=CAU", "96": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQeeM3eJRYM0iIKQV7s7aKaRtugQv7p9vaJVfq22YV2Mp4t53CMvKRHnFiwXvV3UuXCIiI&usqp=CAU", "97": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9SqYifMyZ0JunVdmDfRegc-G6PBSGaBTv9BSdKy40rvu2IW9GKJeln6ZXw5Wvw1mQTDs&usqp=CAU", "98": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTY6WhFfn4n_M7zxvZrPnZ6dpGt_Vds_KlvSexn4BCLADvDEcCDzbT_nzBY4ONaI32qJTw&usqp=CAU", "99": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTOKh7Ue7mQVUNtLGAYbFJ8JabSsMB766_OXWU2HPBL2q-1ymAdTSHBFzfPvc22hJrOKrA&usqp=CAU", "100": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFy9QzW3lN-mibGlX1HTC_8ZQcoz_WvMuH1g&usqp=CAU", "101": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQWWzrBTAE4LY_VEYVmRTxzqkTxXnkSjXiZGw&usqp=CAU", "102": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR2C2hsgcquGeFc6Ls-TBm21qGPOKcDRntOdA&usqp=CAU", "103": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ6varwXIes8UWB4NiRxyrR6XvQS2ja0akEOg&usqp=CAU", "104": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSG3K2Z0-zKcl6KfnIkMUWI2GXsgPRmAlQWPg&usqp=CAU", "105": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpvEZWlKMi6BjJ9H-xdS3WgEjJ4ZdODS0nYg&usqp=CAU", "106": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQYPpXEGFyxj0uSW0XkYcyRSGDRzzRCR0grxg&usqp=CAU", "107": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXvwaSmfomc-SK44D12mrrMx1NEaiatSJ1ZQ&usqp=CAU", "108": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrcW95uUchR2g40OGuzQX8wmqaHxWNtYgH9A&usqp=CAU", "109": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRIjjeEvePntcVN2QuimRv00J_SmoqhMQt6zQ&usqp=CAU", "110": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwvbzPMKTT1upzYgDT_tox4nfVSrwd1n4RoA&usqp=CAU", "111": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-P1IKKg-KD9Oh3kwQwfVtHJnSfRfsBuDhFQ&usqp=CAU", "112": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRCFsk2r5PODfINsC_9GmClRJ8vLqp9tTAb_w&usqp=CAU", "113": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRytjjA6cyYPI7jjODg7nU6kIb__afXQ3WBPA&usqp=CAU", "114": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQLm5XVcUlwE0mYpfULTOnCh1cfNPv_iP2t7g&usqp=CAU", "115": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh_ikOZ2uH0OreJMC7Z1lTcUiVQING-VeIvw&usqp=CAU", "116": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuw7-CCOFdb2zXe3Tc_dnbMq6DWMS6LsLxuw&usqp=CAU", "117": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXqkhu8V5DmWazrp3Oi1vnUIQzxa8zNuveJA&usqp=CAU", "118": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRdfQzmqqEo43RQTJvgylfdZmYkpTVSwKLALQ&usqp=CAU", "119": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAiNwcKYNwjSO1KYBHfdVhjSUD1Nlwat--og&usqp=CAU", "120": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbLUY_GpI8vLtnjDuEeGXOpUUSbI1_41kgyQ&usqp=CAU", "121": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcScWiB0qmrq1EO00HRv2wugJQOdDVL6jsnJgA&usqp=CAU", "122": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzTV1iSzVr9Y9eswADXf3IGkQ5-GpCrBgDaQ&usqp=CAU", "123": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTvR_Kh1glzoOatIKyKJhyg9dOotvOxAIxIrQ&usqp=CAU", "124": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRsvjnRbqv6Fb4IoSerY_DKL13aLetgvFj4CA&usqp=CAU", "125": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQP4im01HJvCQ3Mb6--ilO02ZJ2gD78j-XlzA&usqp=CAU", "126": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQSfkpTF904XmF8d2Krl_QeNLYmk5DhSyeWJA&usqp=CAU", "127": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoas6x28nB-DfSWm7q5yVk_X2i_5vsEs0hNw&usqp=CAU", "128": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSudw5QQ3vmB0UbvLNMRAbvTSjSBxnEl-G2jg&usqp=CAU", "129": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQwRJlo__ltilwtR2D_6uufz8lGbOrVnNFVKQ&usqp=CAU", "130": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTih2tHkZg6enF8zuNEWYicbmkelCUSnks9tQ&usqp=CAU", "131": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRQf0fCyjg4vzOczzcomunZT5wk1LbHya3qTA&usqp=CAU", "132": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdF6kXiofrcXiMyrLLRODsRe09v4ifKdZ4jg&usqp=CAU", "133": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUIjRupmR0QP6L7fau1UT8q_Ilw_zKswZi3A&usqp=CAU", "134": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRL1EeTf6sTJJOrnXguF-9YjmB14j7o1MRdjQ&usqp=CAU", "135": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSAu4dYhJL32aXRUxJKJC4GpLKNekLDbPxUBQ&usqp=CAU", "136": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFxcU3BzbJbBPXkRzh6sXvrfX5FkXDPVzMgQ&usqp=CAU", "137": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTpPj2Xjzv02svymH1xKmtHwsC22PEAFoLcmQ&usqp=CAU", "138": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsgC9GIqTXnqPtyKc6Cs6lI62wD4pc8XDJCg&usqp=CAU", "139": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNajCGwakMfXVVTTQMt8wtf6YAOhpq4jx1VA&usqp=CAU", "140": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBU2L9XwPOJWa_z-GFJgt9ntd1SSQ1y835cw&usqp=CAU", "141": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTq4medtOuzYpHGb22aHQIYSf-LpHWCUyGJ8A&usqp=CAU", "142": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqYWfgwbvxQy_hi7rS3-kuR8Rb9_SO3QspaQ&usqp=CAU", "143": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjt8hI1yJj9RB4xbfWpFiCvGSCuv8LNtgOSg&usqp=CAU", "144": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAN3I3i9cjaVh_fM8P4hyjjT1nppMly4nHXQ&usqp=CAU", "145": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRD7i7SviGTXxAvO6Hp3Wzp6CauQSXD_CYCEw&usqp=CAU", "146": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQRWq4vtmIMXt7RKENmr5X5lcNOhRL6PzEQg&usqp=CAU", "147": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRMx1vpitw7az3JApZG5azshVMhD2vkk-XD0w&usqp=CAU", "148": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSlLxfkCIKD3i_PBGjqWQJlp72RzHUD1KvA_w&usqp=CAU", "149": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQ_zT723jLpkHNhAtxM-0jzuo1KvqOvN9mVw&usqp=CAU", "150": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTlE-2ard1gxmekxjUaESqp7qQyRPzVGzjyug&usqp=CAU", "151": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhhmFWu9lCiMjduwtPZVdTj7wPuLMczprUEw&usqp=CAU", "152": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR51QQ6V3IGAz5sFssx4GFfwPJnSVbTopl_-w&usqp=CAU", "153": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLxa9tVzkosh7udU53CJF-gFNpNkiwkr8R9Q&usqp=CAU", "154": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTv2qQqIbByxCj4tOlo2aspTK90YRZXHAbSmg&usqp=CAU", "155": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQwd-Fwiu4uU6sB8DLKAKYuyUp0ZfAS2AQutg&usqp=CAU", "156": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmcim5iUpgxdf7Ggiq_AAoP6yjCUSjfG-L2A&usqp=CAU", "157": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQB0M2aYhRAnWWZL1ID0ndNz0FxojtqYSCZ6A&usqp=CAU", "158": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSMhgBBVtyFiIZYKbchwqtlnf-R0i-y8LJ6kA&usqp=CAU", "159": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRI4ezjLdOvQtBusl9NIANPzkRD2cxUDSUvVA&usqp=CAU", "160": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSygRLnf27CNEccUgxb9rcddo1argImCCfNNA&usqp=CAU", "161": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbzTwm03eicgyJ5mQTpWSbqpZnMc-zV91RjA&usqp=CAU", "162": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQChMNDSjvoz13y3PJYoMdkFstsPZsR6PKs0g&usqp=CAU", "163": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSjcC-QBOngGrfyoHYUsXbdn-MtDC2yBJDqOw&usqp=CAU", "164": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSnh7Em06jR9TGM8mmu-CMxbqp0N7aD55Q1jQ&usqp=CAU", "165": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRHR6R2N9RpU1HvCX5Rvq1XyR_8rSlqHmPWQQ&usqp=CAU", "166": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSpDnHDWiekEmL7prA-w7OwcZfCJhj0NTKGw&usqp=CAU", "167": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZcnvemZrceyQiht2inAFdA-KNqkA1q3IAaA&usqp=CAU", "168": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFsYoFDB8HkdsFHTrW5Xu9L-irlIsWQBBt_Q&usqp=CAU", "169": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQOdd_TP6FUroT_Fm1QEHHIEHzRi-XGHiksmQ&usqp=CAU", "170": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQLsroH69Yk1G12k-iVXomuSstLRcQmHB44DA&usqp=CAU", "171": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuChXdxV2Gb6-GM4e0UCIklI6u4Rv8PrWHbg&usqp=CAU", "172": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTevGj9oQ_0Wu37SUbv0bf-jnl-rnrAFQjUGQ&usqp=CAU", "173": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTT78mZMYF8F2Zc0sAMn6udX32MZg6Blah80Q&usqp=CAU", "174": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSJ9hMmPualV1xiscBZKfYwIH7LT-hxG_HKGw&usqp=CAU", "175": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRwxwfitUiMvmCAHnzvbTgoCcLkSwSPf519Zg&usqp=CAU", "176": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8MkhaNbQkQ8lNBWUPez5vZXv5lAUcmZBXJA&usqp=CAU", "177": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRczgzFZ4Dgea_DVBby3GNhcLF0PTqRvflj7Q&usqp=CAU", "178": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTELZ4dmWXkkZqDRM92mdoQj__wpQX_WQpdRxUREY2HJNiKcwDk18EwP0Nytid02gPb-Rw&usqp=CAU", "179": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8MkhaNbQkQ8lNBWUPez5vZXv5lAUcmZBXJA&usqp=CAU", "180": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPXBETDGiKnA89MO-Pc2zu8B7qiKvfbAIJO-Bp5kgg6UyIMj8P4P0u29XpSA9HykwJl1M&usqp=CAU", "181": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFhv7Vfri-mxq52QGbcZumaQnumRivIINiK5xhxqIVKSdHBYNrQI5ZTEsuIfdNzfRdjhY&usqp=CAU", "182": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTELZ4dmWXkkZqDRM92mdoQj__wpQX_WQpdRxUREY2HJNiKcwDk18EwP0Nytid02gPb-Rw&usqp=CAU", "183": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRczgzFZ4Dgea_DVBby3GNhcLF0PTqRvflj7Q&usqp=CAU", "184": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR2tuKIBCWZaSJlgBLIOO4oiMQJd9U_MZ085-ZMe9lFIEPTlA2ctKzv6Bbg1Nk9d61vFg8&usqp=CAU", "185": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQNYNm6xyQ_2F0PT1530mT9nj1WpkMfRGPKoA9y5dP7WwIk-tDqnJzjylZ-PmdDD5d3dQA&usqp=CAU", "186": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJhKvIchqYRdPDKBBlwP_lWfP3PPBYtvKAF5Lp-tiFCunJw2SKSjuXvFg1ddZsoAMG_b0&usqp=CAU", "187": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQMUPPAupAatr6rMJL_MZrOci6yBtBtMDsO-67GSOEZBVQkftaq33qmoQ82RBR_Dei5w4&usqp=CAU", "188": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFARvOrqz2JfVwf-DbHMTQr5XrlBQH95f0VgSXnBlHOXU9Kh0Zj2xNvuMSwbAjR9PXPio&usqp=CAU", "189": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT5N6n-CjhKo1DGoSADV0yJMVOGC4b0hrMjYenUYQgxZ_ejhnY2VA4AR8U0V2WORW6M7FM&usqp=CAU", "190": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS5SXUTEuNv7nGeRxBDSszkOrH45LiyjWXM3qAlm1q4Z63XoedBICsBgWaqBVXR3Z1D36o&usqp=CAU", "191": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS09ugMOP3eEbse9DQeF37vcOrq4VGKo8xbeAwXrEOqB_HaZ6aZcT-FV7VbdFUeUNNAQxs&usqp=CAU", "192": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQBu3jaG0oKLFrHmoY3r7yoXHLMIEfQIIm61GdkmnGC-6TzXFNmMaThiJxhM8yxdd5fUo&usqp=CAU", "193": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR7F6jci1vlEzfyGcMPOGgYsKtrMi_PjfhgOe93lNUOvlJbVWb-zwf7hntFHXHLF-swL30&usqp=CAU", "194": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmNwhIod8s-4ptYr21dg724poCavNuyrwr0C_WNsZ1_bHLf2zK0O75Ju7s67kvperFbp4&usqp=CAU", "195": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa1xXIZYWrIEkVFnGhgjm_xMFs1C9Cu3E3SQjXcqpZXTtAxv-VzyCYEki2HMNwzaTxX7g&usqp=CAU", "196": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlgPFT5cE9c_-ZULn6WqwlD0ZqOfLVC6mFsZ0fycET0Dmyf6gWMEKAF-oTLEof6MVDuMw&usqp=CAU", "197": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTu7ED7-P3yNC2DIZWXVZQQ_FQ-RGVmdgjB2rFsHddpzMTmPDlMjuGozWlLK-vgIAhTbEs&usqp=CAU", "198": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJg4fZLZUuVv5wUXdDSA5cLsMvbhnD3M13vw&usqp=CAU", "199": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQb2U5TLaYFsLl3fgvOZJA5Gh1GOBLVzfY0yQ&usqp=CAU", "200": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTL94eCu4Hos6lI4Hi6zrEPmvN2ce5UTTqWKw&usqp=CAU", "201": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRr1WlHqMzSDQvNhl6dZ0tCAcHbetAx7hMtA&usqp=CAU", "202": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBeBJdxjwSxAswREy56t7X1Y9hhwm0wQvHyg&usqp=CAU", "203": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSL9_8uDnHVUCA9sRoyNazPksxeMekyXcysJA&usqp=CAU", "204": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5VTUHOpBZUiZM9EvCWv-z15T0Z2OBmUp7MA&usqp=CAU", "205": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRh-jfSlOpnXQIfDommsI2xu57gKep9HKKEWw&usqp=CAU"} \ No newline at end of file